我有三种型号:
class LevelTwoArea < ActiveRecord::Base
has_many :places, dependent: :restrict
end
class Place < ActiveRecord::Base
belongs_to :level_two_area
has_many :producers, dependent: :restrict
validates_presence_of :level_two_area_id
end
class Producer < ActiveRecord::Base
belongs_to :place
validates_presence_of :place_id
end
我还有一个控制器,每个模型都有一个ActiveScaffold。
问题是,当我想创建一个新的Place
时,脚手架会向日志中抛出一个错误:
ActiveScaffold::ReverseAssociationRequired (Association producers: In order
to support :has_one and :has_many where the parent record is new and the child
record(s) validate the presence of the parent, ActiveScaffold requires the
reverse association (the belongs_to).)
我不明白为什么。。。
注意:
- 其他类似的脚手架也能起作用
我可以在控制台中创建记录并使用关联:
>> Place.new name: 'PONVOGO', level_two_area_id: 10144 => #<Place id: nil, name: "PONVOGO", latitude: nil, longitude: nil, producers_count: nil, level_two_area_id: 10144, created_at: nil, updated_at: nil, marker: nil> >> _.save => true >> Producer.first.place.producers => [#<Producer id: 1, name: "KOFFI YAO GREGOIRE", place_id: 43, created_at: nil, updated_at: nil>]
当我删除
has_many :producers
时,问题消失了,尽管关联宏看起来完全正常- 如果我删除
dependent: :restrict
选项,问题不会消失 - 我在
Place
模型上有一个producers_census
列,我怀疑这会把事情搞砸,但希望在进行大量重构之前得到确认。把这根柱子从脚手架上拆下来并不能解决问题
places
表上的字段:
Column | Type |
--------------------------------------------------
id | integer | non NULL (PK)
name | character varying(50) | non NULL
latitude | double precision |
longitude | double precision |
producers_census | integer |
level_two_area_id | integer | non NULL (FK)
created_at | timestamp without time zone |
updated_at | timestamp without time zone |
marker | geometry |
我的整个PlacesController
:
class PlacesController < ApplicationController
active_scaffold :place do |conf|
conf.columns = :name,
:level_two_area,
:latitude,
:longitude,
:producers_census
export.columns.add :id,
:level_two_area_id
[:latitude, :longitude].each {|column| conf.columns[column].options[:format] = "%.14f" }
[
create,
update,
delete,
batch_update
].each do |action|
action.link.security_method = :can_see_link?
end
batch_destroy.link.each {|sublink| sublink.security_method = :can_see_link? }
end
end
我在铁轨上(3.0.5)/active_scaffold_vho(3.0.17)/rube(1.9.2p180)
虽然我以前从未见过这个ActiveScaffold异常,但我认为这就是正在发生的事情:
反向关联是用:inverse_of
选项设置的,其效果只有在记录未保存时才可见。这就是为什么你在控制台实验中看不到它的原因。
试试这个:
place = Place.new
=> #<Place ...>
producer = place.producers.build
=> #<Producer ...>
producer.place
=> nil
place.producers.first.place
=> nil
当这些记录完全建立在内存中时,将无法通过验证。如果你从来没有同时建造一个地方和一个制片人,那么你就不必担心这一点。然而,如果你这样做了,那么你的验证规则也应该被编写来检查:place
(即对象)的存在,而不是:place_id
:
validates_presence_of :place
我不知道ActiveScaffold使用哪种构建/创建机制,但我猜如果他们抛出这个异常,他们可能会在内存中构建东西。
所以,要解决这个问题,请尝试:
class Producer < ActiveRecord::Base
belongs_to :place, inverse_of: producers
validates_presence_of :place
end
class Place < ActiveRecord::Base
has_many :producers, inverse_of: place
end
注意:ActiveRecord过去在has_many
侧不支持:inverse_of
,该限制曾在源代码中注释。从Rails3.1开始,这个问题似乎已经解决了。如果使用:inverse_of
修改类,如图所示,那么使用内存中对象的控制台实验应该返回关联的对象。
您可能需要查看有关双向关联的Rails API文档