2

我有三个模型:

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如果我删除选项,问题不会消失
  • 我的模型上有一个producers_census专栏Place,我怀疑这会搞砸,但希望在进行大量重构之前得到确认。从脚手架上移除此列不会解决问题。

表上的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) / ruby​​ (1.9.2p180)

4

1 回答 1

3

虽然我以前从未见过这个 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 过去不支持:inverse_ofhas_many并且该限制曾经在源代码中注释。从 Rails 3.1 开始,这似乎是固定的。如果您修改您的类,:inverse_of如图所示,那么使用内存对象的控制台实验应该返回关联的对象。

您可能需要查看有关双向关联的 Rails API 文档

于 2012-02-08T21:55:06.570 回答