2010-05-29 12 views
15

Quiero escribir un named scope para obtener un registro de su identificación.¿Cómo puedo hacer que named_scope en Rails devuelva un valor en lugar de una matriz?

Por ejemplo, tengo un modelo llamado Event, y quiero simular Event.find(id) con el uso de named_scope para flexibilidad futura.

que utiliza este código en mi modelo:

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

y me llaman de mi controlador como Event.from_id(id). Pero mi problema es que devuelve una matriz de Event objetos en lugar de un solo objeto.

Así, si quiero obtener el nombre del evento, tengo que escribir

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

, mientras que lo que quiero es

event = Event.from_id(id) 
event.name 

Estoy haciendo algo mal aquí?

Respuesta

10

Como menciona Damien, no es aconsejable usar un alcance personalizado solo para buscar por ID. Pero para responder a su pregunta:

Encontrar registros con named_scope siempre devolverá un objeto ActiveRecord::NamedScope::Scope, que se comporta como una matriz. Si sólo hay un único registro devuelto por la consulta, puede utilizar el método first para obtener el objeto ActiveRecord directamente como aquí:

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

Hola Jimmy Gracias por la respuesta rápida.Por qué quiero tener un alcance con nombre es (como mencioné en el comentario de Damien) porque más adelante podría querer obtener solo los eventos activos Entonces, puedo cambiar solo el alcance nombrado sin romper el código existente (como solo agregar activo = 1) Déjenme saber sus comentarios, vivas, sameera – sameera207

5

No es necesario utilizar un alcance aquí. Simplemente puede hacer Event.find_by_id id.
La diferencia entre find y find_by_id es que la primera generará un ActiveRecordNotFoundException si el registro no existe. El segundo solo devolverá nil.

Escribir un alcance para obtener el registro por su id es una identificación muy mala, ya que es algo que ya se proporciona de forma nativa por los rieles.

+0

Hola Damien, gracias por la respuesta rápida. Por qué quiero tener esto como un ámbito con nombre es porque más tarde podría querer obtener solo los eventos activos Entonces puedo cambiar solo el alcance nombrado sin romper el código existente (como solo agregar activo = 1) Por favor déjame tus comentarios vítores, sameera – sameera207

+1

@sameera solo podrías agregar un método genérico ('def ... end'); no tiene que ser un alcance designado. –

10

En este caso me gustaría crear un método de clase

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

Otro ejemplo:

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

Métodos como esta su mejor entonces named_scope. Puede llamar al Invoice.number.next, mejor que named_scope devolver Invoice.number[0].next.

Cuestiones relacionadas