sjsc
sjsc

Reputation: 4632

Ruby on Rails: Defining a method with options

I'm looking to define a method that lets me pass options; something like:

@user.tasks(:completed => true)

I thought something like this would work in my user model (but it's not):

User.rb model

  def tasks(options)
    tasks.find(:all, options)
  end

How would I define the method correctly to let me use @user.tasks(:completed => true)?

Upvotes: 3

Views: 7125

Answers (5)

marcgg
marcgg

Reputation: 66436

This is basically how I'd do it:

def tasks(options={})
  unless options[:something].blank? 
    # do stuff
  end
end

There are some different ways to pass options, but you definitively want to pass a hash with a default value (so that you can call the method without options).

In your case the following should address what you want to do:

def tasks(options={})
  Task.find(:all, options[:conditions])
end

Edit: and then call it @thing.tasks( {:conditions => "blah"} )

I haven't tested but it should be ok

Edit 2: But like EmFi said it's not optimal to do this. Consider using an association instead. You'll be able to go @thing.tasks.find(:all, :conditions => {blah})

Upvotes: 6

nas
nas

Reputation: 3696

Activerecord provides a method called with_scope, so to pass any additional conditions

@user.tasks(:completed => true)

you can define the task method as

def tasks(options={})
  with_scope :find => options
    User.all :order => 'id desc'
  end
end

and this will merge any hash passed as options parameter with the actual find

The only caveat is you need to modify your method call slightly

@user.tasks(:conditions => {:completed => true})

or to something like

@user.tasks(:select => 'username')

But if there is an association between user and tasks model then I would do what Jordan has in his post

Upvotes: 0

EmFi
EmFi

Reputation: 23450

Why would you associate a find all on another model with an instance method? I could understand if it was a relation and the find required find options based on the calling record. But there's ActiveRecord Associations for that.

Then there's ActiveRecord::Base#all(options) which is an alias for Task.find(:all, options)

Together make things simpler:

class User < ActiveRecord::Base
  has_many :tasks
end

@user.tasks.all(:conditions => {:completed => true})

Upvotes: 2

Jordan Running
Jordan Running

Reputation: 106027

Does User have a has_many :tasks association? That seems to be what you're after here. In that case Rails provides finders for you, which you can access like this:

@user.tasks.find :all, :conditions => { :completed => true }

Or even shorter:

@user.tasks.all :conditions => { :completed => true }

If that's not terse enough and you always want to use a particular condition, try a named scope:

# In your Task model:    
named_scope :completed, :conditions => { :completed => true }

# Then you can just call...
@some_user.tasks.completed # => Only completed Tasks for @some_user

Upvotes: 5

ennuikiller
ennuikiller

Reputation: 46965

what you need is:

options[:conditions] in your method

Upvotes: 1

Related Questions