当前位置:  开发笔记 > 后端 > 正文

导致此ActiveRecord :: ReadOnlyRecord错误的原因是什么?

如何解决《导致此ActiveRecord::ReadOnlyRecord错误的原因是什么?》经验,为你挑选了5个好方法。

这是在这个先前的问题之后得到回答的.我实际上发现我可以从该查询中删除一个连接,所以现在工作查询是

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

和相关的模特(画面是桌上的球员卡)

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 :tableauDeckCard模型,但它适用于添加到玩家手中.我在DeckCard表中有一个tableau_idhand_id列.

我在rails api中查找了ReadOnlyRecord,并没有超出描述范围.



1> vladr..:

来自ActiveRecord CHANGELOG(2005年10月16日v1.12.0):

引入只读记录.如果你调用object.readonly!然后它会将对象标记为只读,如果调用object.save则引发ReadOnlyRecord.object.readonly?报告对象是否为只读.传递:readonly => true到任何finder方法都会将返回的记录标记为只读. :join连接选项现在暗示:readonly,因此如果使用此选项,则保存相同的记录现在将失败. 使用find_by_sql来解决.

使用find_by_sql并不是一种替代方法,因为它返回原始行/列数据,而不是ActiveRecords.您有两种选择:

    @readonly在记录中强制实例变量为false(hack)

    :include => :card而不是:join => :card

2010年9月更新

以上大部分内容不再适用.因此,在Rails 2.3.4 3.0.0中:

使用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,如果连接表具有比两个外键列越来越: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中应用得很好.

如果你想要实现一个(暗示a ,选择性较低,效率较低),请不要使用.:includesINNER JOIN:includesLEFT OUTER JOININNER JOIN


这可能在最近的版本中已更改,但您只需添加:readonly => false作为find方法属性的一部分.

2> balexand..:

Or in Rails 3 you can use the readonly method (replace "..." with your conditions):

( Deck.joins(:card) & Card.where('...') ).readonly(false)



3> Aaron Rustad..:

这可能在最近发布的Rails中有所改变,但解决此问题的适当方法是在find选项中添加:readonly => false.


我不相信这种情况,至少有2.3.4
它仍然可以与Rails 3.0.10一起使用,这是我自己的代码中的示例,该示例获取具有以下内容的范围:join Fundraiser.donatable.readonly(false)

4> bronson..:

select('*')似乎在Rails 3.2中解决了这个问题:

> Contact.select('*').joins(:slugs).where('slugs.slug' => 'the-slug').first.readonly?
=> false

只是为了验证,省略select('*')会产生一个只读记录:

> Contact.joins(:slugs).where('slugs.slug' => 'the-slug').first.readonly?
=> true

不能说我理解其基本原理,但至少它是一个快速而干净的解决方法.


在Rails 4中也是如此.或者你可以做`select(quoted_table_name +'.*')`

5> 小智..:

而不是find_by_sql,你可以在finder上指定一个:select,一切都很开心......

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

推荐阅读
凹凸曼00威威_694
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有