Как создать rails habtm, который удаляет / уничтожает без ошибок?
-
21-09-2019 - |
Вопрос
Я создал простой пример для проверки работоспособности и, похоже, до сих пор не могу уничтожить элемент по обе стороны отношения has_and_belongs_to_many в rails.
Всякий раз, когда я пытаюсь удалить объект из любой таблицы, я получаю страшное сообщение об ошибке NameError / "неинициализированная константа".
Чтобы продемонстрировать, я создал пример приложения rails с классами Boy и Dog.Я использовал базовый каркас для каждого из них и создал таблицу ссылок под названием boys_dogs .Затем я добавил простую процедуру before_save, позволяющую создавать новую "собаку" каждый раз, когда был создан мальчик, и устанавливать отношения, просто чтобы упростить настройку.
собака.рб
class Dog < ActiveRecord::Base
has_and_belongs_to_many :Boys
end
мальчик.рб
class Boy < ActiveRecord::Base
has_and_belongs_to_many :Dogs
def before_save
self.Dogs.build( :name => "Rover" )
end
end
схема.rb
ActiveRecord::Schema.define(:version => 20100118034401) do
create_table "boys", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "boys_dogs", :id => false, :force => true do |t|
t.integer "boy_id"
t.integer "dog_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "dogs", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Я видел много сообщений здесь и в других местах о подобных проблемах, но решения обычно используют belongs_to, а имена классов во множественном числе / единственном числе путаются.Я не думаю, что здесь дело в этом, но я попытался переключить инструкцию habtm на использование имени в единственном числе, просто чтобы посмотреть, помогло ли это (безуспешно).Кажется, я упускаю здесь что-то простое.
Фактическое сообщение об ошибке является:
Ошибка имени в BoysController#уничтожить
неинициализированный постоянный Мальчик::Собаки
След выглядит как:
/Библиотека/Ruby/Gems/1.8/gems/activesupport-2.3.4/Библиотека/active_support/dependencies.rb:105:в
const_missing'
destroy_without_callbacks'
(eval):3:in
/Библиотека/Ruby/Gems/1.8/gems/activerecord-2.3.4/Библиотека/active_record/обратные вызовы.rb:337:вdestroy_without_transactions'
отправить'
/Library/Ruby/Gems/1.8/gems/activerecord-2.3.4/lib/active_record/transactions.rb:229:in
...
Спасибо.
Решение
Я не вижу вашего обратного вызова destroy, но я вижу пару проблем.Во-первых, ваши ассоциации должны быть в нижнем регистре.Так что dog.rb должен быть:
class Dog < ActiveRecord::Base
has_and_belongs_to_many :boys
end
и boy.rb должен быть:
class Boy < ActiveRecord::Base
has_and_belongs_to_many :dogs
def before_save
self.dogs.build( :name => "Rover" )
end
end
Во-вторых, я полагаю, что вы хотите использовать self.dogs.create
вместо того , чтобы self.dogs.build
выше, поскольку сборка фактически не сохранит новый объект dog.
Другие советы
Принятый здесь ответ решил мою проблему, только для того, чтобы создать еще одну.
Вот мои модельные объекты:
class Complex < ActiveRecord::Base
set_table_name "Complexes"
set_primary_key "ComplexID"
has_and_belongs_to_many :amenities
end
class Amenity < ActiveRecord::Base
set_table_name "Amenities"
set_primary_key "AmenityID"
end
Rails использует имя ассоциации в качестве имени таблицы при создании запроса select.Мое приложение работает в Unix с устаревшей базой данных MySQL, а имена моих таблиц чувствительны к регистру и не соответствуют соглашениям Rails.Всякий раз, когда мое приложение действительно пыталось загрузить ассоциацию, я получал исключение, что MySQL не смог найти таблицу amenities
:
SELECT * FROM `amenities`
INNER JOIN `ComplexAmenities` ON `amenities`.AmenityID = `ComplexAmenities`.AmenityID
WHERE (`ComplexAmenities`.ComplexID = 147 )
Я искал и искал и не мог найти способ указать Rails использовать правильный регистр для имени таблицы.В отчаянии я попытался передать :table_name
опция для habtm, и это сработало.Моя новая сложная модель выглядит следующим образом:
class Complex < ActiveRecord::Base
set_table_name "Complexes"
set_primary_key "ComplexID"
has_and_belongs_to_many :amenities, :table_name => 'Amenities'
end
Это работает под управлением Rails 2.3.5.
Этот вариант является не упоминается в документах Ruby on Rails.