Re: Why joins queries make result readonly?

160 views
Skip to first unread message

Frederick Cheung

unread,
May 14, 2013, 6:12:01 AM5/14/13
to rubyonra...@googlegroups.com


On Tuesday, May 14, 2013 10:26:56 AM UTC+1, Илья Воронцов wrote:
Are there any rationalies to make queries obtained by joining scope to be readonly? I read some old posts (pre-rails3) that joins adds additional columns to record so that ActiveRecord doesn't know how to update that fields, but actually I don't see that fields. For example I write model
class Order < ActiveRecord::Base
  has_and_belongs_to_many :executors, class_name: 'Specialist', join_table: 'order_executors'
  scope :by_executor, ->(executor_id) { joins(:executors).where(specialists: {id: executor_id} ) }
end

and make query Order.by_executor(1) so that I get:

Order Load (2.0ms)  SELECT "orders".* FROM "orders" INNER JOIN "order_executors" ON "order_executors"."order_id" = "orders"."id" INNER JOIN "specialists" ON "specialists"."id" = "order_executors"."specialist_id" WHERE "specialists"."id" = 1
=> [#<Order id: 20, orderable_id: 11, orderable_type: "PlanDevelopment", client_id: 1, completion_status: "finished", created_at: "2013-05-13 20:48:19", updated_at: "2013-05-14 00:36:38", price: #<BigDecimal:67e5898,'0.14E2',9(36)>>]

I see no additional columns but Order.by_executor(1).first.readonly? is true. Is that necessary?

p.s. Yes I know that I can set readonly(false) or explicitly specify select clause - so that records won't become readonly. But I want to understand why this blocking behavior is necessary (if it is still true) and what damage will be possible without readonly mark? Also I don't understand, how can I shot myself if I explicitly set readonly(false).

This might be a hangover from the past - I think active record didn't use to default to orders.* - the default select clause was select *.

The danger is only if you do select columns from the other tables. This can either prevent saves (because your object has an attribute that doesn't exist for the model) or mask existing data, eg if both of the joined tables have a client_id column and you do select * then the activerecord object will have a single client_id attribute that has only one of those values.

Fred 

Colin Law

unread,
May 14, 2013, 6:14:56 AM5/14/13
to rubyonra...@googlegroups.com
Should the OP be using includes rather than joins?

Colin

Frederick Cheung

unread,
May 14, 2013, 6:19:32 AM5/14/13
to rubyonra...@googlegroups.com, cla...@googlemail.com


On Tuesday, May 14, 2013 11:14:56 AM UTC+1, Colin Law wrote:

Should the OP be using includes rather than joins?


Hard to tell.

Fred 

Frederick Cheung

unread,
May 14, 2013, 6:21:12 AM5/14/13
to rubyonra...@googlegroups.com
On Tuesday, May 14, 2013 10:26:56 AM UTC+1, Илья Воронцов wrote:

Order Load (2.0ms)  SELECT "orders".* FROM "orders" INNER JOIN "order_executors" ON "order_executors"."order_id" = "orders"."id" INNER JOIN "specialists" ON "specialists"."id" = "order_executors"."specialist_id" WHERE "specialists"."id" = 1
=> [#<Order id: 20, orderable_id: 11, orderable_type: "PlanDevelopment", client_id: 1, completion_status: "finished", created_at: "2013-05-13 20:48:19", updated_at: "2013-05-14 00:36:38", price: #<BigDecimal:67e5898,'0.14E2',9(36)>>]

I see no additional columns but Order.by_executor(1).first.readonly? is true. Is that necessary?

One other thing: inspect only ever shows columns from the model table - If you change the select clause to orders.*, order_executors.specialist_id then you'd get the same inspect output but your object would respond to specialist_id

Fred

Илья Воронцов

unread,
May 14, 2013, 6:56:41 AM5/14/13
to rubyonra...@googlegroups.com
Thank you, Frederik.
I think in my case joins is better because I don't want any orders except those having exact executor (with includes I'll get lots of orders without any executor at all, if I understand its behavior right)
I tried to get specialist_id and got nothing. So it looks, there is actually no column foreign columns on default join.
Reply all
Reply to author
Forward
0 new messages