Question

I am a beginner in Rails and i have a problem with scope.

I have my class with 2 scopes :

class Event < ActiveRecord::Base
  belongs_to :continent
  belongs_to :event_type 

   scope :continent, lambda { |continent|
     return if continent.blank?
     composed_scope = self.scoped
     composed_scope = composed_scope.where('continent_id IN ( ? )', continent).all
     return composed_scope
   }

   scope :event_type, lambda { |eventType|
     return if eventType.blank?
     composed_scope = self.scoped
     composed_scope = composed_scope.where('event_type_id IN ( ? )', eventType).all
     return composed_scope
   }

end

And in my controller i want to use this 2 scopes at the same time. I did :

def filter
  @event = Event.scoped
  @event = @event.continent(params[:continents]) unless params[:continents].blank?
  @event = @event.event_type(params[:event_type]) unless params[:event_type].blank?

  respond_with(@event)
end

But i doesn't work, I have this error :

 undefined method `event_type' for #<Array:0x7f11248cca80>

It's because the first scope return an array.

How can I do to make it work?

Thank you !

Was it helpful?

Solution

You should not append '.all' in your scopes:

It transforms a chainable ActiveRelation into an Array, by triggering the SQL query.

So simply remove it.

Bonus:

Some refactoring:

scope :continent, lambda { |continent|   
  self.scoped.where('continent_id IN ( ? )', continent) unless continent.blank?
}

OTHER TIPS

I don't think you need .scoped in your scopes.

def filter
  @event = Event.scoped
  @event = @event.continent(params[:continents]) unless params[:continents].blank?
  @event = @event.event_type(params[:event_type]) unless params[:event_type].blank?

  respond_with(@event)
end

on the code above you already have everything returning as 'scoped'. Plus, your scopes wouldnt need an 'unless' on them, since they will only be called if your params arent blank. So your scopes could become something like this

scope :continent, lambda { |continent|   
  where('continent_id IN ( ? )', continent)
}

or, on a more Rails 3 way,

scope :continent, lambda { |continent_id|
  where(:continent_id => continent_id)
}

which is much shorter :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top