Как добавить записи в has_many: через объединение в рельсах
class Agents << ActiveRecord::Base
belongs_to :customer
belongs_to :house
end
class Customer << ActiveRecord::Base
has_many :agents
has_many :houses, through: :agents
end
class House << ActiveRecord::Base
has_many :agents
has_many :customers, through: :agents
end
Как добавить к модели Agents
для Customer
?
Это лучший способ?
Customer.find(1).agents.create(customer_id: 1, house_id: 1)
Вышеописанное прекрасно работает с консолью, но я не знаю, как это сделать в реальном приложении.
Представьте, что форма заполнена для клиента, который также принимает house_id
в качестве ввода. Затем я делаю следующее в своем контроллере?
def create
@customer = Customer.new(params[:customer])
@customer.agents.create(customer_id: @customer.id, house_id: params[:house_id])
@customer.save
end
В целом я смущен тем, как добавлять записи в таблицу has_many :through
?
Ответы
Ответ 1
Я думаю, вы можете просто сделать это:
@cust = Customer.new(params[:customer])
@cust.houses << House.find(params[:house_id])
Или при создании нового дома для клиента:
@cust = Customer.new(params[:customer])
@cust.houses.create(params[:house])
Ответ 2
"Лучший способ" зависит от ваших потребностей и того, что чувствует себя наиболее комфортно. Путаница возникает из-за различий поведения ActiveRecord методов new
и create
и оператора <<
.
Метод new
new
не добавит вам запись ассоциации. Вы должны сами создать записи House
и Agent
:
house = @cust.houses.new(params[:house])
house.save
agent = Agent(customer_id: @cust.id, house_id: house.id)
agent.save
Обратите внимание, что @cust.houses.new
и House.new
фактически одинаковы, потому что вам нужно создать запись Agent
в обоих случаях.
Оператор <<
Как упоминает Миша, вы также можете использовать оператор <<
в коллекции. Это создаст для вас модель Agent
, вы должны построить модель House
:
house = House.create(params[:house])
@cust.houses << house
agent = @cust.houses.find(house.id)
Метод create
create
построит для вас как записи House
, так и Agent
, но вам нужно будет найти модель Agent
, если вы намереваетесь вернуть ее в свое представление или api:
house = @cust.houses.create(params[:house])
agent = @cust.agents.where(house: house.id).first
В качестве заключительного замечания, если вы хотите, чтобы при создании House
возникали исключения, используйте вместо этого команды bang (например, new!
и create!
).
Ответ 3
Другим способом добавления ассоциаций является использование столбцов внешнего ключа:
agent = Agent.new(...)
agent.house = House.find(...)
agent.customer = Customer.find(...)
agent.save
Или используйте точные имена столбцов, передавая идентификатор связанной записи, а не записи.
agent.house_id = house.id
agent.customer_id = customer.id