在Rails中创建具有关联的对象

时间:2017-09-27 09:38:21

标签: ruby-on-rails ruby

在我的Rails应用程序中,我有客户端和用户。用户可以拥有许多客户端。

模型设置如下:

class Client < ApplicationRecord
  has_many :client_users, dependent: :destroy
  has_many :users, through: :client_users
end

class User < ApplicationRecord
  has_many :client_users, dependent: :destroy
  has_many :clients, through: :client_users
end

class ClientUser < ApplicationRecord
  belongs_to :user
  belongs_to :client
end

因此,如果我想创建一个新客户端,其前两个用户与之关联,我该怎么做?

e.g。

Client.create!(name: 'Client1', client_users: [User.first, User.second])

尝试这会给我一个错误:

ActiveRecord::AssociationTypeMismatch: ClientUser(#70142396623360) expected, got #<User id: 1,...

我也想为RSpec测试做这个。 e.g。

user1 = create(:user)
user2 = create(:user)

client1 = create(:client, client_users: [user1, user2])

如何在Rails控制台和RSpec测试中创建具有关联用户的客户端?

5 个答案:

答案 0 :(得分:2)

如果你不想接受任何事情的accept_nested_attributes,那么你也可以将块传递给create。here

Client.create!(name: 'Client1') do |client1| 
  client1.users << [User.find(1), User.find(2), User.find(3)]     
end

答案 1 :(得分:1)

试试这个。它应该工作

  

Client.create!(name:'Client1')。client_users.new([{user_id:   User.first},{user_id:User.second}])

答案 2 :(得分:1)

您可以使用以下代码执行此操作:

user1 = create(:user)
user2 = create(:user)

client1 = create(:client, users: [user1, user2])

有关文档

,请参阅ClassMethods/has_many
  

集合=对象

     

通过删除和添加对象来替换集合内容   适当。如果:through选项是连接中的真回调   除了破坏回调之外,模型被触发,因为删除是   直接

如果您使用factory_girl,可以像这样添加trait :with_users

FactoryGirl.define do
  factory :client do

    trait :with_two_users do
      after(:create) do |client|
        client.users = create_list :user, 2
      end
    end

  end
end

现在,您可以在测试中为用户创建一个客户端,如下所示:

client = create :client, :with_two_users

答案 3 :(得分:0)

  

accepts_nested_attributes_for:users

并按原样行事:

  

Client.create!(name: 'Client1', users_attributes: { ........ })

希望这对你有用。

答案 4 :(得分:0)

您遇到不匹配的原因是因为您指定了client_users关联,希望ClientUser个实例,但您正在传递User实例:

# this won't work
Client.create!(client_users: [User.first, User.second])

相反,由于您已经指定了users关联,因此可以执行此操作:

Client.create!(users: [User.first, User.second])

但是,有一种更简单的方法可以解决这个问题:抛弃连接模型并使用has_and_belongs_to_many关系。您仍然需要数据库中的clients_users联接表,但您不需要ClientUser模型。 Rails将自动处理这个问题。

class Client < ApplicationRecord
  has_and_belongs_to_many :users
end

class User
  has_and_belongs_to_many :clients
end

# Any of these work:
client = Client.new(name: "Kung Fu")
user = client.users.new(name: "Panda")
client.users << User.new(name: "Nemo")
client.save # => this will create two users and a client, and add two records to the `clients_users` join table