2016-09-20 38 views
1

说,我有这些模型:Has_many虽然 - 如何在Rails 4中添加模型?

class Account < ActiveRecord::Base 
     has_many :account_games, :dependent => :destroy 
     has_many :games, :through => :account_games 
    end 

    class Game < ActiveRecord::Base 
     has_many :account_games, :dependent => :destroy 
     has_many :accounts, :through => :account_games 
    end 

    class AccountGame < ActiveRecord::Base 
     belongs_to :account 
     belongs_to :game 

     validates :account, presence: true 
     validates :game, presence: true 
    end 

我知道我可以在Rails 3中做到这一点:

@account = Account.new(params[:user]) 
@accountgame = @account.account_games.build(:game => Game.first, :score => 100) 
@accountgame.save 

更新:

# or 
@account = Account.new(params[:user]) 
@account.games << Game.first 
# what's next? any other setting required and if so where? 

也就是说,我已经有一个游戏我想将其添加到帐户。我如何在Rails 4中做到这一点?

+4

应该是相同的......你得到一个错误? – dinjas

+0

你曾试过'@account.account_games << @ accountgame' ?.您可能需要使用':autosave => true'选项,以便ActiveRecord自动保存关系。 – yeyo

+0

@yeyo,在哪个模型? – Johshi

回答

1

准确地说你正在使用什么版本的Rails?我无法通过4.2.5.1下的新Rails应用程序重新创建您的问题。

迁移:

Account迁移:

class CreateAccounts < ActiveRecord::Migration 
    def change 
    create_table :accounts do |t| 
     t.timestamps null: false 
    end 
end 
end 

Game迁移:

class CreateGames < ActiveRecord::Migration 
    def change 
    create_table :games do |t| 
     t.timestamps null: false 
    end 
    end 
end 

AccountGame迁移:

class CreateAccountGames < ActiveRecord::Migration 
    def change 
    create_table :account_games do |t| 
     t.references :account 
     t.references :game 
     t.integer :score 
     t.timestamps null: false 
    end 
    end 
end 

Account模型(APP /模型/ account.rb):

class Account < ActiveRecord::Base 
    has_many :account_games, dependent: :destroy 
    has_many :games, through: :account_games 
end 

Game模型(APP /模型/ game.rb):

class Game < ActiveRecord::Base 
    has_many :account_games, dependent: :destroy 
    has_many :accounts, through: :account_games 
end 

AccountGame模型(APP /模型/ account_game.rb) :

class AccountGame < ActiveRecord::Base 
    belongs_to :account 
    belongs_to :game 

    validates :account, presence: true 
    validates :game, presence: true 
end 

使用它:

Loading development environment (Rails 4.2.5.1) 
>> g = Game.create 
    (0.1ms) begin transaction 
    SQL (1.1ms) INSERT INTO "games" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2016-09-20 03:31:41.484101"], ["updated_at", "2016-09-20 03:31:41.484101"]] 
    (1.0ms) commit transaction 
=> #<Game id: 2, created_at: "2016-09-20 03:31:41", updated_at: "2016-09-20 03:31:41"> 
>> a = Account.new 
=> #<Account id: nil, created_at: nil, updated_at: nil> 
>> a.account_games.build(game: Game.first, score: 100) 
    Game Load (0.2ms) SELECT "games".* FROM "games" ORDER BY "games"."id" ASC LIMIT 1 
=> #<AccountGame id: nil, account_id: nil, game_id: 1, score: 100, created_at: nil, updated_at: nil> 
>> a.save 
    (0.1ms) begin transaction 
    SQL (0.4ms) INSERT INTO "accounts" ("created_at", "updated_at") VALUES (?, ?) [["created_at", "2016-09-20 03:32:02.532976"], ["updated_at", "2016-09-20 03:32:02.532976"]] 
    SQL (0.2ms) INSERT INTO "account_games" ("game_id", "score", "account_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["game_id", 1], ["score", 100], ["account_id", 2], ["created_at", "2016-09-20 03:32:02.535031"], ["updated_at", "2016-09-20 03:32:02.535031"]] 
    (1.0ms) commit transaction 
=> true 
>> a.account_games 
    AccountGame Load (0.2ms) SELECT "account_games".* FROM "account_games" WHERE "account_games"."account_id" = ? [["account_id", 2]] 
=> #<ActiveRecord::Associations::CollectionProxy [#<AccountGame id: 2, account_id: 2, game_id: 1, score: 100, created_at: "2016-09-20 03:32:02", updated_at: "2016-09-20 03:32:02">]> 

你也可以这样做:

>> a.account_games.count 
    Account Load (0.1ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = ? LIMIT 1 [["id", 2]] 
    (0.1ms) SELECT COUNT(*) FROM "account_games" WHERE "account_games"."account_id" = ? [["account_id", 2]] 
=> 1 

>> a.games << Game.first 
    Game Load (0.2ms) SELECT "games".* FROM "games" ORDER BY "games"."id" ASC LIMIT 1 
    (0.2ms) begin transaction 
    SQL (0.4ms) INSERT INTO "account_games" ("account_id", "game_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["account_id", 2], ["game_id", 1], ["created_at", "2016-09-20 04:52:07.058592"], ["updated_at", "2016-09-20 04:52:07.058592"]] 
    (0.8ms) commit transaction 
    Game Load (0.2ms) SELECT "games".* FROM "games" INNER JOIN "account_games" ON "games"."id" = "account_games"."game_id" WHERE "account_games"."account_id" = ? [["account_id", 2]] 
=> #<ActiveRecord::Associations::CollectionProxy [#<Game id: 1, created_at: "2016-09-20 03:24:16", updated_at: "2016-09-20 03:24:16">, # <Game id: 1, created_at: "2016-09-20 03:24:16", updated_at: "2016-09-20 03:24:16">, #<Game id: 1, created_at: "2016-09-20 03:24:16", updated_at: "2016-09-20 03:24:16">]> 
>> a.account_games.count 
    Account Load (0.1ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = ? LIMIT 1 [["id", 2]] 
    (0.1ms) SELECT COUNT(*) FROM "account_games" WHERE "account_games"."account_id" = ? [["account_id", 2]] 
=> 2 

我假设你Game是有效的?例如。 Game.first.valid? == true

+0

我有一系列游戏,这就是为什么我这样做“a.accounts << my_games”,但它在account.errors中说“account_games无效”。它的轨道4.0 – Johshi

+0

我在我的答案结尾添加了另一个我认为你正在做的事情的例子。您没有展示过这三种模型中的任何其他验证吗?你是否使用了正确的语法(因为你的评论^^与你的问题相比似乎并不准确) – dinjas

0

在Rails 4.0.9

@account = Account.new(params[:user]) 
account_game_datas = [{game_id: 1, score: 100}, {game: 2, score: 110}] 
@accountgame = @account.account_games.build(account_game_datas) 
@accountgame.save 

它的工作原理一样rails4。

您可以通过这些使用NEST:

# model 
class Account < ActiveRecord::Base 
    has_many :account_games, :dependent => :destroy 
    has_many :games, :through => :account_games 
    accepts_nested_attributes_for :account_games 
end 

# controller 
params[:user][:account_games_attributes] = [{game_id: 1, score: 100}, {game: 2, score: 110}] 
@account = Account.create(user_params) 

private 
def user_params 
    params.require(:user).permit(..., account_games_attributes: [:game_id, :score]) 
end 
相关问题