6
votes

I have a scope that returns an Array instead of an ActiveRecord Relation when it is called, but if I call the methods within the scope, it returns an ActiveRecord Relation.

scope :beta_user, -> {
  joins(:config).where("config_type = 'Model' AND opts #>> '{beta}' = 'true'")
}

# Calling scope directly
Model.beta_user # => [Model1, Model2, Model3]
Model.beta_user.class # => Array

# Calling scope definition
Model.joins(:config).where("config_type = 'Model' AND opts #>> '{beta}' = 'true'") 
=> [Model1, Model2, Model3]

Model.joins(:config).where("config_type = 'Model' AND opts #>> '{beta}' = 'true'").class
=> Model::ActiveRecord_Relation

So my question here is, what's going on with the inconsistent return types? I'm unable to chain other scopes after this (I can still chain them before it) and I can't use other AR Relation methods such as #order and #pluck.

From what I can see in the console, it seems like calling Model.beta_user.class is still executing the query whereas Model.joins(:config).where("config_type = 'Model' AND opts #>> '{beta}' = 'true'") does not execute the query. I thought a scope was not supposed to execute until it needed to in order to optimize for chained scopes/queries.

1
can you check it with class method instead of scope ...? - uzaif
Have you taken a look at this answer to see if this is the same cause? stackoverflow.com/a/7901640/3366016 - user3366016

1 Answers

0
votes

A scope indeed returns a relation object, however it will convert it when necessary, when you run the scope in your console it will try to inspect it and will do the conversion.

But try this, it should work:

scope = Model.beta_user

# pluck should work
scope.pluck(:id)

And all the other methods like first, last, count, all, etc... should work