ActiveScaffold::ReverseAssociationRequired ошибка для создания новой записи
У меня есть три модели:
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 ответ
Хотя я никогда не видел этого исключения 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 на предмет двунаправленных ассоциаций