2016-09-20 54 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