What Is Causing This Activerecord::Readonlyrecord Error

What is causing this ActiveRecord::ReadOnlyRecord error?

Rails 2.3.3 and lower

From the ActiveRecord CHANGELOG(v1.12.0, October 16th, 2005):

Introduce read-only records. If you call object.readonly! then it will
mark the object as read-only and raise
ReadOnlyRecord if you call
object.save. object.readonly? reports
whether the object is read-only.
Passing :readonly => true to any
finder method will mark returned
records as read-only. The :joins
option now implies :readonly, so if
you use this option, saving the same
record will now fail.
Use find_by_sql
to work around.

Using find_by_sql is not really an alternative as it returns raw row/column data, not ActiveRecords. You have two options:

  1. Force the instance variable @readonly to false in the record (hack)
  2. Use :include => :card instead of :join => :card

Rails 2.3.4 and above

Most of the above no longer holds true, after September 10 2012:

  • using Record.find_by_sql is a viable option
  • :readonly => true is automatically inferred only if :joins was specified without an explicit :select nor an explicit (or finder-scope-inherited) :readonly option (see the implementation of set_readonly_option! in active_record/base.rb for Rails 2.3.4, or the implementation of to_a in active_record/relation.rb and of custom_join_sql in active_record/relation/query_methods.rb for Rails 3.0.0)
  • however, :readonly => true is always automatically inferred in has_and_belongs_to_many if the join table has more than the two foreign keys columns and :joins was specified without an explicit :select (i.e. user-supplied :readonly values are ignored -- see finding_with_ambiguous_select? in active_record/associations/has_and_belongs_to_many_association.rb.)
  • in conclusion, unless dealing with a special join table and has_and_belongs_to_many, then @aaronrustad's answer applies just fine in Rails 2.3.4 and 3.0.0.
  • do not use :includes if you want to achieve an INNER JOIN (:includes implies a LEFT OUTER JOIN, which is less selective and less efficient than INNER JOIN.)

What is causing this ActiveRecord::ReadOnlyRecord error?

Rails 2.3.3 and lower

From the ActiveRecord CHANGELOG(v1.12.0, October 16th, 2005):

Introduce read-only records. If you call object.readonly! then it will
mark the object as read-only and raise
ReadOnlyRecord if you call
object.save. object.readonly? reports
whether the object is read-only.
Passing :readonly => true to any
finder method will mark returned
records as read-only. The :joins
option now implies :readonly, so if
you use this option, saving the same
record will now fail.
Use find_by_sql
to work around.

Using find_by_sql is not really an alternative as it returns raw row/column data, not ActiveRecords. You have two options:

  1. Force the instance variable @readonly to false in the record (hack)
  2. Use :include => :card instead of :join => :card

Rails 2.3.4 and above

Most of the above no longer holds true, after September 10 2012:

  • using Record.find_by_sql is a viable option
  • :readonly => true is automatically inferred only if :joins was specified without an explicit :select nor an explicit (or finder-scope-inherited) :readonly option (see the implementation of set_readonly_option! in active_record/base.rb for Rails 2.3.4, or the implementation of to_a in active_record/relation.rb and of custom_join_sql in active_record/relation/query_methods.rb for Rails 3.0.0)
  • however, :readonly => true is always automatically inferred in has_and_belongs_to_many if the join table has more than the two foreign keys columns and :joins was specified without an explicit :select (i.e. user-supplied :readonly values are ignored -- see finding_with_ambiguous_select? in active_record/associations/has_and_belongs_to_many_association.rb.)
  • in conclusion, unless dealing with a special join table and has_and_belongs_to_many, then @aaronrustad's answer applies just fine in Rails 2.3.4 and 3.0.0.
  • do not use :includes if you want to achieve an INNER JOIN (:includes implies a LEFT OUTER JOIN, which is less selective and less efficient than INNER JOIN.)

Ruby on Rails: How do I get rid of the ActiveRecord:ReadOnlyRecord error?

If you loaded link_pages via an ARel :join query, you can probably get rid of the error by changing :join to :include.

A similar question with a more detailed answer was answered here.

How can this code throw a ActiveRecord::ReadOnlyRecord exception?

This is probably due to joining in other child values through your find_by_code() helper.

When ActiveRecord uses joins to lookup an object returning additional values, it marks the record read-only.

There's a thorough description of this on this question here:

What is causing this ActiveRecord::ReadOnlyRecord error?

If this is the case, you can probably fix the issue by turning a your :joins into a proper :include that populates the ActiveRecord instances without marking them read-only.

ActiveRecord::ReadOnlyRecord: Diff is marked as readonly on destroy_all

With includes, Rails will determine whether to use multiple queries (using preload) or a single left outer join query (using eager_load). In your case, because your where clause is on the association, Rails will use eager_load and therefore a LEFT OUTER JOIN. Also note that associations loaded via a join are marked as readonly and is the cause of the error you're receiving. The solution is to switch includes to left_joins and set readonly(false) prior to calling destroy_all.

Snippet.left_joins(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all

NOTE

I originally thought you could do

Snippet.includes(:diffs).readonly(false).where(diffs: { body: "<div class=\"diff\"></div>"}).destroy_all

but this doesn't work for some reason (and don't have enough time to investigate atm). In any case, since using includes would result in a LEFT OUTER JOIN anyways, you can use the above solution to get the desired outcome.

Rails 3 scoped finds giving ActiveRecord::ReadOnlyRecord

It turns out it was related to using scopes to impersonate active record associations. I was able to fix it by adding .readonly(false) to my scopes.

Why does this activerecord find query throw an error?

Error: Couldn't find all Movies with 'id': (all, {:order=>"title"})

@movies = Movie.find(:all, :order => (params[:sort]))

That's because the above query only works in Rails 2.x and older. In the later versions of Rails that query won't work!

Checked here, and the first snippet seems it should valid:
https://apidock.com/rails/ActiveRecord/Base/find/class

You are looking into older version of Rails(2.3.8). You can find the reference to newer versions here



Related Topics



Leave a reply



Submit