This project is archived and is in readonly mode.

#4589 ✓invalid
VirtualFunction

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

    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

    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

    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

    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

    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>

Pages