ActiveScaffold :: ReverseAssociationRequired ошибка для создания новой записи - PullRequest
2 голосов
/ 01 февраля 2012

У меня есть три модели:

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)

1 Ответ

3 голосов
/ 09 февраля 2012

Хотя я никогда раньше не видел этого исключения 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_of на стороне has_many, и это ограничение раньше комментировалось в источнике.Начиная с Rails 3.1 это кажется исправленным.Если вы измените свои классы с помощью :inverse_of, как показано, то консольный эксперимент с объектами в памяти должен вернуть связанный объект.

Возможно, вы захотите просмотреть документы Rails API по двунаправленным ассоциациям

...