RonLugge
RonLugge

Reputation: 5174

Why is this scope causing recusion in my rails app?

scope :name, -> (name){ where "lower(name) LIKE ?", "%#{name.downcase}%"}

I have a model with a name property. When I query that property directly, everything works fine. When I try to dry it up with the above scope, I start getting stack level errors -- somehow, that scope is causing recursion even on a Client.where(true) statement. Even if I change it from name to number, on the off chance I'm somehow conflicting with a built-in method, it doesn't work. What am I overlooking?

Relevant model:

class Client < ActiveRecord::Base

  scope :name, -> (name){ where "lower(name) LIKE ?", "%#{name.downcase}%"}
end

with schema:

create_table "clients", force: true do |t|
  t.string   "name"
  t.string   "number"
  t.string   "email",            null: false
  # Other columns omitted for brevity, nothing unusual or odd about them.
end

Upvotes: 0

Views: 33

Answers (1)

cschroed
cschroed

Reputation: 6834

The problem is that your scope is named name. The name method normally returns the class name. Some Rails code makes use of the name method, such as the parent_name method in the introspection module:

def parent_name
  if defined? @parent_name
    @parent_name
  else
    @parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil  # This line calls the "name" method
  end
end  

parent_name can take a class name like Admin::User and return Admin.

Methods like parent_name are used by core functions like compute_table_name in the ModelSchema. The compute_table_name logic and the current_scope logic can get mixed up in a loop when a scope is named name. This leads to stack level too deep errors.

You can avoid this by altering your scope to something like:

scope :by_name, ->(name) { where "lower(name) LIKE ?", "%#{name.downcase}%" }

Upvotes: 3

Related Questions