1

Ruby on Rails と ActiveRecord に関する私の理解から、パラメーターが ID を探しているときに、ID の代わりに ActiveRecord モデル自体を使用できます。たとえば、Fooモデルでbelongs_toあるモデルがある場合、の代わりにBar書くことができます。しかし、今作っているモデル(囲碁アプリ用)ではそうではないようです。bar = Bar.new(foo_id: foo)bar = Bar.new(foo_id: foo.id)

モデルからの関連コードは次のとおりです。

class User < ActiveRecord::Base
  .
  .
  .
  has_many :participations, dependent: :destroy
  has_many :games, through: :participations
end

class Game < ActiveRecord::Base
  attr_accessible :height, :width

  has_many  :participations, dependent: :destroy
  has_many  :users, through: :participations

  def black_player
    self.users.joins(:participations).where("participations.color = ?", false).first
  end

  def white_player
    self.users.joins(:participations).where("participations.color = ?", true).first
  end
end

class Participation < ActiveRecord::Base
  attr_accessible :game_id, :user_id, :color

  belongs_to :game
  belongs_to :user

  validates_uniqueness_of :color, scope: :game_id
  validates_uniqueness_of :user_id, scope: :game_id
end

(色はブール値で、false = 黒、true = 白)

(id=1) とUsers( id=2) の2 つと を作成した場合、次のようにできます。black_playerwhite_playerGame game

game.participations.create(user_id: black_player, color: false)

そしてgame.participationsblack_player.participations両方ともこの新しいものを示していますParticipation:

=> #<Participation id: 1, game_id: 1, user_id: 1, color: false, created_at: "2012-10-10 20:07:23", updated_at: "2012-10-10 20:07:23">

ただし、次に試してみると:

game.participations.create(user_id: white_player, color: true)

次に、newParticipationの auser_idは 1 (black_player の ID) です。同じゲームで重複したプレイヤーに対して検証したため、これは有効Participationではなく、データベースに追加されません。

=> #<Participation id: nil, game_id: 1, user_id: 1, color: true, created_at: nil, updated_at: nil> 

しかし、もしそうなら:

game.participations.create(user_id: white_player.id, color: true)

それはうまくいきます:

=> #<Participation id: 2, game_id: 1, user_id: 2, color: true, created_at: "2012-10-10 20:34:03", updated_at: "2012-10-10 20:34:03"> 

この動作の原因は何ですか?

4

2 に答える 2

2

:belongs_to 子オブジェクトに直接渡された親オブジェクトはブール値に変換されるため、id が 1 になるようです。解決策の 1 つは、最初にオブジェクトを開始してから、保存する前に親オブジェクトを直接設定することです。

@participation = Participation.new
@participation.game = @game
@participation.user = @user
@participation.color = false
@participation.save

もう 1 つは、オブジェクトの代わりに ID を渡すことです。これは、現在行っている方法と同じです。

編集:以下はそうではなく、情報を残しています:

userの代わりに使用してみてくださいuser_id:

game.participations.create(user: white_player, color: true)

リレーションの代わりに列名を明示的に指定しているため、ユーザーオブジェクトから整数を取得しようとしている可能性があると思います。"#<User:0x107f8a2f2584e0>"その後、1になるか、文字列で見つかった最初の有効な数字になりUser.find(2).to_s.to_iます。あなたの場合は1を返す必要があります。

于 2012-10-10T20:58:10.913 に答える
0

ActiveRecordが関連付けを処理します。ただし、上記のコードから2つの問題が発生する可能性があります。まず、オブジェクト「user」を属性「user_id」に割り当てようとしています。次に、その'user'は、Participationクラスのインスタンスのmass_assignmentには使用できません。作成の呼び出しにハッシュを渡すことによってオブジェクトに属性を割り当てることは「mass_assignment」と呼ばれ、ハッカーがそれらを望まない可能性のある属性を割り当てるために使用できます。そのため、railsは「attr_accessible」メソッドを提供します。クラス定義の「attr_accessible」メソッドにシンボルとして渡すことにより、「mass_assignment」中にユーザーが設定できる属性を明示的に宣言する必要があります。

attr_accessible :game, :user, :color

今、あなたはすることができます

game.participations.create(:user => my_player_object)

それでも状況によっては「Id」を割り当てたい場合は、それをattr_accessibleにも渡す必要があることに注意してください。

attr_accessible :game, :user, :color, :game_id, :user_id
于 2012-10-11T03:33:36.173 に答える