как добавить записи в has_many: через ассоциацию в рельсах - PullRequest
89 голосов
/ 04 сентября 2011
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?

Ответы [ 3 ]

146 голосов
/ 04 сентября 2011

Я думаю, вы можете просто сделать это:

 @cust = Customer.new(params[:customer])
 @cust.houses << House.find(params[:house_id])

Или при создании нового дома для клиента:

 @cust = Customer.new(params[:customer])
 @cust.houses.create(params[:house])

Вы также можете добавить с помощью идентификаторов:

@cust.house_ids << House.find(params[:house_id])
72 голосов
/ 08 августа 2013

«Лучший способ» зависит от ваших потребностей и того, что вам наиболее удобно. Путаница возникает из-за различий в поведении 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

В заключение: если вы хотите, чтобы при создании * 1039 возникали исключения, используйте вместо этого операторы взрыва (например, new! и create!).

5 голосов
/ 29 января 2015

Другой способ добавления ассоциаций - использование столбцов внешнего ключа:

agent = Agent.new(...)
agent.house = House.find(...)
agent.customer = Customer.find(...)
agent.save

Или используйте точные имена столбцов, передавая идентификатор связанной записи вместо записи.

agent.house_id = house.id
agent.customer_id = customer.id
...