3

dear all, i have a Student model that i've specified some name_scope in it, e.g. from_program, from_year, from_school, has_status, from_course, etc...

is there anyway that i can chain the different named_scope together dynamically depending on certain criterias during runtime?

for example, if the user accessing the data is from Finance, i want to be able to chain from_school and has_status together only. if the user is the lecturer, i want to be able to chain from_course, from_school together, and so on...

should i use named_scope? or should i just fall back to the good old way of specifying conditions?

thanks for your suggestions in advance! =) btw i'm using rails 2.3

Staelen
  • 7,691
  • 5
  • 34
  • 30

2 Answers2

5

I'm not sure, if I understood, but I think you could do something like this:

class Student

  named_scope from_program, lambda{|program| :conditions => {:program => program}}
  named_scope from_year, lambda{|year| :conditions => {:year => year}}
  named_scope has_status, lambda{|status| :conditions => {:status => status}}

  def self.from_finance(school, status)
    self.from_school(school).has_status(status)
  end

end

or more general

def self.get_students(params)
  scope = self
  [:program, :year, :school, :course].each do |s|
    scope = scope.send("from_#{s}", params[s]) if params[s].present?
  end
  scope = scope.has_status(params[:status]) if params[:status].present?
  scope
end
santuxus
  • 3,662
  • 1
  • 29
  • 35
  • yeah you get what i need to achieve, but your general case isn't getting the result because when you do a `send`, the `named_scope` runs immediately, thus it's not chaining all the named_scopes together =( i try to avoid the first method as the criterias can get very fine as they are allowed to specify what group of students they wish to retrieve based on the scopes alr allowed... =( but thanks for your suggestion though, very close! – Staelen Mar 10 '11 at 09:00
  • you're welcome! ;] About general method: I've tested it and for combined named scopes (added by the name or by send) it is still ok, producing only 1 query... I have an app where I used this approach and if I do in console _Order.send(:edited).send(:by_code, 3)_ I get _Order Load (0.3ms) SELECT * FROM `orders` WHERE ((code LIKE '%3%') AND (`orders`.`status` = 'edition'))_ – santuxus Mar 10 '11 at 10:35
  • i've tried running using this way, but it didn't return any results, it just return the Student class itself... – Staelen Mar 11 '11 at 01:34
2

You can try something like this

  Class User extend ActiveRecord::Base
  belongs_to :semester

  named_scope :year, lambda { |*year|
    if year.empty? || year.first.nil?
      { :joins => :semester, :conditions => ["year = #{CURRENT_SEMESTER}"]}
    else
      { :joins => :semester, :conditions => ["year = #{year}"]}
    end
    }

  end

You can call like this

  User.year     # defaults to CURRENT_SEMESTER constant
  User.year()  # same as above
  User.year(nil)  # same as above; useful if passing a param value that may or may not exist, ie, param[:year]
  User.year(2010)

In the same way you can pass parameters

Ashish
  • 5,723
  • 2
  • 24
  • 25