17

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?

3 Answers 3

13

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.

Sign up to request clarification or add additional context in comments.

Comments

10

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

1 Comment

hi Jimmy Thanks for the quick answer. Why I want to have a named scope is (as I mentioned in Damien's comment) because later I might want to get only the active events So then I can change only the named scope with out breaking the existing code (like only adding active=1) Please let me know your comments cheers, sameera
5

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.

2 Comments

Hi Damien, thanks for the quick reply. Why i want to have this as a named scope is because later I might want to get only the active events So then I can change only the named scope with out breaking the existing code (like only adding active=1) Please let me know your comments cheers, sameera
@sameera you could just add a generic method (def ... end); it doesn't have to be a named scope.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.