Reputation: 16629
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
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
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
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