注意: 关于 SO 有很多旧的 Q/A,其中人们要么 (1) 尝试设置关联的
列,或者 (2) 设置计数器缓存的has_one_id
列,或者(3) 在测试期间,当测试数据库尚未运行迁移时设置它。这些不是我的问题。count
在我的 Rails 7.1.4 应用程序中,我刚刚向我的
locations
表添加了一个迁移,该表添加了 box_area
列。保存时,该列的值将根据其他列的值计算。
但是 ActiveModel 不允许我向该列保存任何值。我不明白为什么。我已经运行了迁移。该列显示在 schema.rb 中。
根据 mysql,这是数据库表的当前状态:
mysql> SHOW COLUMNS FROM locations;
+-----------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+----------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
| user_id | int | YES | | NULL | |
| north | float | YES | | NULL | |
| south | float | YES | | NULL | |
| west | float | YES | | NULL | |
| east | float | YES | | NULL | |
| name | varchar(1024) | YES | | NULL | |
| box_area | decimal(21,10) | YES | | NULL | |
+-----------------+----------------+------+-----+---------+----------------+
以下是 ActiveRecord 关于该列的说明:
irb(main):003> Location.columns
...
#<ActiveRecord::ConnectionAdapters::MySQL::Column:0x0000000108870d30
@collation=nil,
@comment=nil,
@default=nil,
@default_function=nil,
@name="box_area",
@null=true,
@sql_type_metadata=#<ActiveRecord::ConnectionAdapters::SqlTypeMetadata:0x0000000108870fb0 @limit=nil, @precision=21, @scale=10, @sql_type="decimal(21,10)", @type=:decimal>>]
要分配值,我在模型上使用
before_save
回调:
before_save :calculate_box_area
def calculate_box_area
self.box_area = calculate_area
end
def calculate_area
# math
end
如果我在回调中中断,我可以看到
self.box_area
=> 0.2428601638665e3
但是保存时出现错误。
can't write unknown attribute `box_area` (ActiveModel::MissingAttributeError)
我尝试过这个,在
rails console
:
irb(main):001> loc = Location.new(north: 4, south: 3, east: 5, west: 4, user_id: 1, name: "glade")
irb(main):002> loc.save
(irb):9:in `<main>: can't write unknown attribute `box_area` (ActiveModel::MissingAttributeError)`
irb(main):010> loc.attributes
=>
{"id"=>nil,
"created_at"=>Sun, 29 Sep 2024 04:48:58.000000000 EDT -04:00,
"updated_at"=>Sun, 29 Sep 2024 04:48:58.000000000 EDT -04:00,
"user_id"=>1,
"north"=>4.0,
"south"=>3.0,
"west"=>4.0,
"east"=>5.0,
"name"=>"glade",
"box_area"=>0.123449675887591e5}
为什么?这是怎么回事?
我不确定在 mysql 中我们需要填写完整的属性。如果添加
box_area: 0.0
有效吗?
Location.new(北:4,南:3,东:5,西:4,user_id:1,名称:“空地”,box_area:0.0)
如果是我的话。我会这样处理
box_area
change_column(:locations, :box_area, :float, default: 0.0)
class Location < ActiveRecord::Base
after_initialize :init
def init
self.box_area ||= 0.0
end
end
如果有人有更好的解决方案,请告诉我。谢谢