This project is archived and is in readonly mode.
Issues with scopes/association proxies lazy/enum behavior ...
Reported by VirtualFunction | May 13th, 2010 @ 06:49 AM
This seems to have crapped up in trunk in recent days...
lets say I have a setup like this:
class User < ActiveRecord::Base
has_many :channels
end
class Channel < ActiveRecord::Base
scope :audio, where(:classification => 'audio')
end
Assuming each user has some related audio channels, if I do something like:
User.first.channels.audio.select &:nil?
I would expect an empty array. However it appears the 'select &:nil?' bit is not working, as it returns the same results as User.first.channels.audio (as I say above, assuming all users have channels)
If I take out the audio scope and do something like:
User.first.channel_user_permissions.select &:nil? that seems to work.
Comments and changes to this ticket
-
VirtualFunction May 13th, 2010 @ 06:50 AM
OK, looks like this is specifically a scope issue, association proxies without scopes seem OK. For instance this fails:
Channel.audio.select &:nil?
-
VirtualFunction May 13th, 2010 @ 06:51 AM
For your info, I'm using the trunk version of Rails, it's a streaming fresh copy, about few hours old.
-
Neeraj Singh May 14th, 2010 @ 04:17 AM
I spent some time looking into this issue and this is what I found.
class Brake scope :good, where(:quality => 'good') end Brake.all.class #=> Array Brake.good.select #=> ActiveRecord::Relation
Actually you were unlucky to encounter 'select'. Instead of 'select' if you try 'collect' or 'map' they will work fine.
Why is it so?
Well Brake.unscoped returns ActiveRecord::Relation. This class has following statement.
ASSOCIATION_METHODS = [:includes, :eager_load, :preload] MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having] SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from]
ActiveRecord::Relation declares a method for all the items in the array. That method returns an instance of ActiveRecor::Relation. So 'select' method returns an instance of ActiveRecord::Relation so that you can do things like this.
rails console > unscoped = Brake.unscoped; nil > unscoped.select(:id) SELECT id FROM "brakes" > unscoped.inspect SELECT "brakes".* FROM "brakes"
So in this case 'select' is being used to select what columns should be picked up.
You will also find following statement in ActiveRecord::Relation
delegate :length, :collect, :map, :each, :all?, :include?, :to => :to_a
It means that operations like 'map' and 'collect' would work fine.
Back to original problem
One solution could be to rename select to select_query so that select could be used for enumeration purpose.
I will post it on the mailing list and will see what the core team says.
-
VirtualFunction May 14th, 2010 @ 01:03 PM
OK, thanks for getting back. Yes I should I've realized this this myself tbh... My bad, probably due to a lack of sleep.
Could be worth making this clear in the documentation when the final release is made given the ambiguity of expectation here. Just another idea that's all along with the select_query concept (given that the "find" method also has the same ambiguity).
Given that enum has a find_all method that is aliased to select, I'll probably use that (or just call "all" prior to that to coerce things to an Enum)
-
Santiago Pastorino May 14th, 2010 @ 11:24 PM
- State changed from new to invalid
Yeah select at this point returns a Relation object which represents the query to be executed and doesn't execute it. Lazy Load :).
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>