sameera207
sameera207

Reputation: 16629

How can I make named_scope in Rails return one value instead of an array?

I want to write a named scope to get a record from its id.

For example, I have a model called Event, and I want to simulate Event.find(id) with use of named_scope for future flexibility.

I used this code in my model:

named_scope :from_id, lambda { |id| {:conditions => ['id= ?', id] } }

and I call it from my controller like Event.from_id(id). But my problem is that it returns an array of Event objects instead of just one object.

Thus if I want to get event name, I have to write

event = Event.from_id(id)
event[0].name

while what I want is

event = Event.from_id(id)
event.name

Am I doing something wrong here?

Upvotes: 17

Views: 14970

Answers (3)

Gianpaulo
Gianpaulo

Reputation: 332

In this case I'd create a class method

def self.from_id(id)
  self.find(id).first
end

Another example:

class Invoice
  def self.number
    self.find(:first, 
      :select => "max(number) As last, max(number)+1 As next", 
      :conditions => "type = 'SalesOrder'")
  end
end

Methods like this its better then named_scope. You can call Invoice.number.next, better than named_scope return Invoice.number[0].next.

Upvotes: 13

Jimmy
Jimmy

Reputation: 37081

As Damien mentions, using a custom scope just to look up by ID isn't advisable. But to answer your question:

Finding records with named_scope will always return an ActiveRecord::NamedScope::Scope object, which behaves like an array. If there is just a single record returned by your query, you can use the first method to get the ActiveRecord object directly, like this:

event = Event.from_id(id).first
event.name # will work as you expect

Upvotes: 10

Damien MATHIEU
Damien MATHIEU

Reputation: 32629

There's no need to use a scope here. You could just do Event.find_by_id id.
The difference between find and find_by_id is that the first one will raise an ActiveRecordNotFoundException if the record does not exist. The second one will just return nil.

Writing a scope to get the record by it's id is a very bad id as it is something which is already provided natively by rails.

Upvotes: 5

Related Questions