1. ホーム
  2. ruby-on-rails

[解決済み】ActiveRecord::ReadOnlyRecordのエラーの原因は何ですか?

2022-05-05 03:09:19

質問

これは以下の通りです。 これ の前の質問で、回答がありました。実は、このクエリからジョインを削除できることがわかりました。

start_cards = DeckCard.find :all, :joins => [:card], :conditions => ["deck_cards.deck_id = ? and cards.start_card = ?", @game.deck.id, true]  

これはうまくいくように見えます。しかし、これらのDeckCardsを別の関連付けに移動させようとすると、ActiveRecord::ReadOnlyRecordエラーが発生します。

以下はそのコードです。

for player in @game.players 
  player.tableau = Tableau.new
  start_card = start_cards.pop 
  start_card.draw_pile = false
  player.tableau.deck_cards << start_card  # the error occurs on this line
end

と関連するModels(tableauはテーブル上のプレイヤーカード)

class Player < ActiveRecord::Base
  belongs_to :game
  belongs_to :user
  has_one :hand
  has_one :tableau
end

class Tableau < ActiveRecord::Base
  belongs_to :player
  has_many :deck_cards
end  

class DeckCard < ActiveRecord::Base
  belongs_to :card
  belongs_to :deck  
end

このコードの直後で、同様の動作をしています。 DeckCards を選手の手に渡すと、そのコードは問題なく動作しています。私は belongs_to :tableau のDeckCardモデルで、プレイヤーの手札に追加するのは問題なく動作します。ただし tableau_idhand_id カラムを作成します。

rails apiでReadOnlyRecordを調べてみましたが、説明以上のことは書いてありませんね。

どのように解決するのですか?

Rails 2.3.3以下

から ActiveRecord CHANGELOG (v1.12.0、2005年10月16日) :

<ブロッククオート

読み取り専用レコードを導入する。 object.readonly! オブジェクトを読み取り専用としてマークし を呼び出すと、ReadOnlyRecordが表示されます。 object.save。 object.readonly? オブジェクトが読み取り専用かどうか。 に :readonly => true を渡します。 ファインダメソッドは、返された レコードを読み取り専用にします。 を使用すると、:joins オプションは :readonly を意味するようになったので、もし このオプションを使用した場合、同じ のレコードは失敗するようになりました。 find_by_sqlを使用します。 で回避できます。

使用方法 find_by_sql は、行/列の生データを返すので、実際には代替案にはなりません。 ActiveRecords . 2つの選択肢があります。

  1. インスタンス変数を強制的に @readonly をfalseに設定する必要があります(ハック)。
  2. 使用方法 :include => :card の代わりに :join => :card

Rails 2.3.4以上

2012年9月10日以降、上記のほとんどは適用されなくなりました。

  • 使用 Record.find_by_sql 実行可能な選択肢
  • :readonly => true は自動的に推論されます のみ もし :joins が指定された場合 なし 明示的な :select また 明示的な(あるいはファインダースコープ継承の) :readonly オプションの実装を参照してください。 set_readonly_option!active_record/base.rb の実装はRails 2.3.4用、あるいは to_aactive_record/relation.rb との custom_join_sqlactive_record/relation/query_methods.rb Rails 3.0.0用)
  • が、しかし :readonly => true には常に自動的に推論されます。 has_and_belongs_to_many 結合テーブルが2つ以上の外部キーカラムを持ち、かつ :joins を明示的に指定せずに :select (すなわち、ユーザーが提供する :readonly の値は無視されます。 finding_with_ambiguous_select?active_record/associations/has_and_belongs_to_many_association.rb .)
  • 結論として、特殊なジョインテーブルと has_and_belongs_to_many であれば @aaronrustad の回答は、Rails 2.3.4 と 3.0.0 で問題なく適用されます。
  • する ではなく 使用 :includes を実現したい場合は INNER JOIN ( :includes を意味する。 LEFT OUTER JOIN よりも選択性が低く、効率も悪い。 INNER JOIN .)