11

If you use joins in an ARel scope, the result becomes read-only (i.e. you cannot update any of the records you get back). If you would not like the result to be read-only, you just chain readonly(false) to the scope, e.g.

User.joins(:orders).where(:orders => { :state => 'completed' }).readonly(false)

But I'm guessing that there is a reason why the join-scopes by default are read-only. What is the reason behind setting the results to read-only?

Thomas Watson
  • 6,507
  • 5
  • 33
  • 43

1 Answers1

1

Interesting question. I was googling around.....With a joins query, you're getting back a single record with the User + order table attributes. If you tried to update one of the attributes (say "order_num") in the order table instead of the User table, the update statement to the User table wouldn't be able to find order_num and would crash. So the join-scopes are read-only by default to prevent that from happening.

References: 1) http://blog.ethanvizitei.com/2009/05/joins-and-namedscopes-in-activerecord.html
2) Proper way to prevent ActiveRecord::ReadOnlyRecord?

Community
  • 1
  • 1
  • 2
    As far as I can see, the `SELECT` query only returns the user attributes - *not* the order attributes, since it's doing a `SELECT users.* FROM ...`. So the returned ActiveRecord object(s) should not contain any order attributes as far as I can understand – Thomas Watson Aug 04 '12 at 13:03
  • I also see it just returning the original model's content. It makes it difficult to use joins in a default scope. I use joins in a default scope to filter out non-active records based on a hierarchical model ecosystem (e.g. if the Order is "inactive" then the order_lines should not be returned by default. Thus OrderLine default_scope { joins(:order) } and Order default_scope { where(active: true) }. – TJChambers Sep 21 '14 at 22:22