This project is archived and is in readonly mode.

#3766 open
Stephan Kaag

On-the-fly created named-scope raises 'undefined method `call' when called from subclass with cache_classes = true

Reported by Stephan Kaag | January 21st, 2010 @ 04:42 PM | in 2.3.10

Summary:

I create a named_scope at runtime (a pattern that searchlogic (http://github.com/binarylogic/searchlogic) also relies on). When the named-scope is first called on the super class an error is raised when I call that same scope in the subclass. I am not familiar enough with the codebase to provide a solution myself.

This error occurs in both Rails 2.3.5 and 3.0pre.

To reproduce:

Rails3::Application.configure do
  config.cache_classes = true
end

class Candidate < ActiveRecord::Base
  def self.create_second_order_scope
    return if respond_to?(:second_order)
    named_scope :second_order, :conditions => {}
  end
end

class Admin::Candidate < Candidate
end

Error trigger:

Candidate.create_second_order_scope
Candidate.second_order
Admin::Candidate.create_second_order_scope
Admin::Candidate.second_order
>> undefined method `call' for nil:NilClass

Comments and changes to this ticket

  • Stephan Kaag

    Stephan Kaag February 1st, 2010 @ 09:36 AM

    Is anyone experiencing this same problem?

  • Matt Jones

    Matt Jones February 4th, 2010 @ 09:27 PM

    • Assigned user set to “Matt Jones”

    I've experienced this EXACT problem, in the Hobo project which does automatic scope generation much like this.

    See this ticket for more info, and the commit at the end of the ticket for a tweak that may help your case. As you can see in the ticket, I was supposed to have already made a ticket for this here... :)

    If it works for you, I'll see about writing up a patch + some tests (you're welcome to give it a try as well).

  • Espen Antonsen

    Espen Antonsen April 15th, 2010 @ 07:16 PM

    Same problem here. Rails 2.3.5. Using STI.

  • Santiago Pastorino

    Santiago Pastorino June 24th, 2010 @ 10:22 PM

    • Milestone cleared.
    • State changed from “new” to “open”

    Can someone create a test case following https://rails.lighthouseapp.com/projects/8994/sending-patches
    Thanks.

  • Neeraj Singh

    Neeraj Singh June 25th, 2010 @ 01:44 AM

    I am not able to reproduce this problem with rails3 edge.

    ActiveRecord::Schema.define(:version => 20100624220122) do
    
      create_table "users", :force => true do |t|
        t.string   "name"
        t.datetime "created_at"
        t.datetime "updated_at"
      end
    
    end
    class User < ActiveRecord::Base
      def self.create_second_order_scope
        return if respond_to?(:second_order)
        named_scope :second_order, :conditions => {}
      end
    
      def self.lab
        User.create_second_order_scope
        puts User.second_order.all.inspect
      end
    end
    
    class Admin::User < User
      def self.lab
        Admin::User.create_second_order_scope
        puts Admin::User.second_order.all.inspect
      end
    end
    
    # User.lab #=> produces sql query
    # Admin::User.lab #=> produces sql query
    
  • Santiago Pastorino

    Santiago Pastorino June 25th, 2010 @ 02:56 AM

    Neeraj did you do config.cache_classes = true? What about 2-3-stable?

  • Neeraj Singh

    Neeraj Singh June 25th, 2010 @ 03:54 AM

    @Santiago I just did User.lab and Admin::User.lab in production environment and I get the same result.

    will try with 2-3 and will let you know.

  • Matt Jones

    Matt Jones June 25th, 2010 @ 04:04 AM

    @Neeraj: at least in Rails 2.3.x, the issue is caused by the scope's method being propagated up the inheritance chain, while the scope conditions are not. The trick is that the scopes are stored in an inheritable attribute - not a big deal for 3.0, since the methods are defined in-place without an actual reference to the array (see around line 89 in named_scopes.rb on master). On 2.3.x, the method that's defined only references the array:

    define_method name do |*args|
      scopes[name].call(self, *args)
    end
    

    Thus, in Admin::User above, you end up with a second_order method inherited from the parent, but scopes[:second_order] returns nil since the subclass has an empty hash which was inherited from the parent at definition time.

  • Neeraj Singh

    Neeraj Singh June 25th, 2010 @ 10:10 PM

    I can confirm that it is indeed and error with 2-3-stable. But it works fine on rails3 edge.

  • Neeraj Singh

    Neeraj Singh June 25th, 2010 @ 10:10 PM

    • Tag changed from 2.3.5, 3.0pre, named_scope to 2.3.5, named_scope
  • Santiago Pastorino

    Santiago Pastorino June 25th, 2010 @ 10:13 PM

    • Milestone set to 2.3.9
    • Tag changed from 2.3.5, named_scope to named_scope
  • Jeremy Kemper

    Jeremy Kemper August 30th, 2010 @ 02:28 AM

    • Milestone changed from 2.3.9 to 2.3.10
    • Importance changed from “” to “Low”
  • mrcsparker

    mrcsparker October 18th, 2010 @ 11:36 PM

    I put together some code based on the Hobo link placed here. I am still testing it, but it seems to work so far. Once I am sure that it works, I will put together the patch.

    Here is the change to lib/active_record/named_scope.rb against 2.3.10

    def named_scope(name, options = {}, &block)

        name = name.to_sym
    
        scopes[name] = lambda do |parent_scope, *args|
          Scope.new(parent_scope, case options
            when Hash
              options
            when Proc
              if self.model_name != parent_scope.model_name
                options.bind(parent_scope).call(*args)
              else
                options.call(*args)
              end
          end, &block)
        end
    
        singleton_class.send :define_method, name do |*args|
          scopes[name].call(self, *args)
        end
    
        _name = name.to_sym
        _scope = scopes[_name]
        subclasses.each do |s|
          s.scopes[_name] = _scope
        end
    
      end
    end
    
  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:29 PM

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:29 PM

    • State changed from “open” to “stale”
  • Ryan Burrows

    Ryan Burrows February 14th, 2011 @ 09:08 PM

    I just ran into this today on Rails 2.3.10 uses searchlogic.

    I've attached a patch with a test that exposes the bug on Rails 2.3 stable and a fix for the issue. The fix is basically mrcsparker's fix above.

  • Ryan Burrows

    Ryan Burrows February 14th, 2011 @ 09:23 PM

    • State changed from “stale” to “open”

    Forgot to open the ticket

    [state:open]

  • bingbing

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>

Attachments

Pages