Rails: имеет и принадлежит многим (HABTM) - создает ассоциацию без создания других записей
Провел весь день в Google, но не нашел ответа.:\
У меня есть связь HABTM между пользователями и Core_Values.
class CoreValue < ActiveRecord::Base
has_and_belongs_to_many :users
class User < ActiveRecord::Base
has_and_belongs_to_many :core_values
В моем контроллере мне нужно сделать две отдельные вещи:
- Если CoreValue не существует, создайте новый и сопоставьте его с данным идентификатором пользователя и
- Предполагая, что я знаю, что определенный CoreValue уже существует, создайте ассоциацию, не создавая никаких новых CoreValues или Users
Для # 1 у меня есть это для работы:
User.find(current_user.id).core_values.create({:value => v, :created_by => current_user.id})
Это создает новый CoreValue с: значением и: created_by и создает ассоциацию.
Для # 2 я пробовал несколько вещей, но, похоже, не могу создать ассоциацию ТОЛЬКО.
Спасибо за вашу помощь!
Ответы
Ответ 1
Вы можете сделать это в двухэтапной процедуре, используя очень полезный метод find_or_create
. find_or_create
сначала попытается найти запись, а если она не существует, создайте ее. Что-то вроде этого должно сделать трюк:
core_value = CoreValue.find_or_create_by_value(v, :created_by => current_user.id)
current_user.core_values << core_value
Некоторые примечания:
- Первая строка найдет или создаст значение
v
. Если он не существует и создан, он установит created_by
в current_user.id
.
- Нет необходимости делать
User.find(current_user.id)
, так как это возвращает тот же объект, что и current_user
.
-
current_user.core_values
- это массив, и вы можете легко добавить к нему другое значение, используя <<
.
Для краткости следующее будет таким же, как пример кода выше:
current_user.core_values << CoreValue.find_or_create_by_value(v, :created_by => current_user.id)
Ответ 2
Добавьте метод в свою модель пользователя:
class User < ActiveRecord::Base
def assign_core_value(v)
core_values.find_by_name(v) || ( self.core_values <<
CoreValue.find_or_create_by_name(:name => v, :created_by => self)).last
end
end
Метод assign_core_value
удовлетворяет требованию 1,2 и возвращает значение ядра, назначенное пользователю (с заданным именем).
Теперь вы можете сделать следующее:
current_user.assign_core_value(v)
Примечание 1
Логика метода выглядит следующим образом:
1) Проверяет, связан ли CoreValue с пользователем. Если это не предпринимается, значение ядра возвращается.
2) Проверяет, существует ли CoreValue с заданным именем. Если не создается CoreValue. Связывает основное значение (созданное/найденное) с пользователем.
Ответ 3
Активная запись уже дает вам метод. В вашем случае
val = CoreValue.find_by_value(v)
current_user.core_values << val
Вы также можете передать несколько объектов таким образом. Все ассоциации будут созданы
Отметьте этот для получения дополнительной информации