2010-01-28 8 views
7

Decir que tengo la siguiente asociación con una condición adjunto:¿Cuál es el propósito de: condiciones en una asociación belongs_to?

belongs_to :admin_user, 
    :class_name => 'User', 
    :foreign_key => :admin_user_id, 
    :conditions=> 'users.admin=TRUE' # or any variation with hash or array, {:admin => true}, etc. 

El API doc states que la opción: condiciones en belongs_to será:

especificar las condiciones que la objeto asociado debe cumplir para para ser incluido como WHERE SQL fragmento, como autorizado = 1.

Pero el resultado no muestra ninguna cláusula WHERE en la selección, y en cualquier caso, esperaría que condiciones como esta en un belongs_to evitarían persistir en esa relación, en el INSERT no en el SELECT. Esta opción parece no tener efecto en una asociación belongs_to, a menos que me falta algo. La opción tiene sentido en un has_many, simplemente no veo cómo se aplica a belongs_to.

EDITAR: Investigaciones adicionales revelan que puede persistir una asociación que infringe una condición, pero no puede recuperar el registro asociado después de el registro se vuelve a cargar.

En una clase definida de esta manera:

class Widget < ActiveRecord::Base 

    belongs_to :big_bloop, 
     :class_name => "Bloop", 
     :foreign_key => :big_bloop_id, 
     :conditions => ["big_bloop = ?", true] 

    belongs_to :bloop, :conditions => ["big_bloop = ?", true] 

end 

... desde la consola vemos:

>> bloop = Bloop.new 
=> #<Bloop id: nil, name: nil, big_bloop: nil> 
>> widget = Widget.new 
=> #<Widget id: nil, name: nil, bloop_id: nil, big_bloop_id: nil> 
>> widget.bloop = bloop 
=> #<Bloop id: nil, name: nil, big_bloop: nil> 
>> widget.save! 
=> true 
>> widget 
=> #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: nil> 

me he asociado un bloop que viole la condición y la salvó. La asociación persiste en el archivo db (consulte bloop_id y big_bloop_id en la última línea anterior).

>> big_bloop = Bloop.new 
=> #<Bloop id: nil, name: nil, big_bloop: nil> 
>> widget.big_bloop = big_bloop 
=> #<Bloop id: nil, name: nil, big_bloop: nil> 
>> widget.save! 
=> true 
>> widget 
=> #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: 3> 

Lo mismo, diferente atributo.

>> widget.bloop 
=> #<Bloop id: 2, name: nil, big_bloop: nil> 
>> widget.big_bloop 
=> #<Bloop id: 3, name: nil, big_bloop: nil> 

Ambos bloqueos no válidos permanecen en la memoria.

>> widget.reload 
=> #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: 3> 
>> widget.bloop 
=> nil 
>> widget.big_bloop 
=> nil 

Después de la recarga, se han ido, porque la instrucción SELECT efectivamente utiliza una cláusula WHERE para excluirlos.

Bloop Load (0.3ms) SELECT * FROM `bloops` WHERE (`bloops`.`id` = 2 AND (big_bloop = 1)) 

Y, sin embargo el widget todavía tiene las referencias:

>> widget 
=> #<Widget id: 2, name: nil, bloop_id: 2, big_bloop_id: 3> 

me parece extraño, pero hay que ir.

Respuesta

4

¡Es un buen descubrimiento!

Mi primer pensamiento fue que esto podría ser solo algo genérico de la clase base AssociationProxy o similar. Sin embargo, la excavación más abajo, parece que hay una lista de opciones específicas belongs_to permisos:

@@valid_keys_for_belongs_to_association = [ 
    :class_name, :primary_key, :foreign_key, :foreign_type, :remote, :select, :conditions, 
    :include, :dependent, :counter_cache, :extend, :polymorphic, :readonly, 
    :validate, :touch 
] 

Por lo tanto, en algún momento, se tomó la decisión de poner posiblemente subconsciente que hay. :)

No estoy seguro de cómo ha probado el DONDE.Mi prueba muestra claramente que hace incluyen la cláusula WHERE:

class Thing < ActiveRecord::Base; end 

class Widget < ActiveRecord::Base 
    belongs_to :thing, :conditions => ['name = ?', 'Jigglymabob'] 
end 

Thing.create :name => 'Jigglymabob' 
# => #<Thing id: 1, name: "Jigglymabob"> 
w = Widget.create :name => 'Wookeleywoo', :thing_id => 1 
# => #<Widget id: 1, name: "Wookeleywoo", thing_id: 1> 
w.thing 
# => #<Thing id: 1, name: "Jigglymabob"> 

Después de todo esto, mi archivo de registro contiene:

Thing Create (0.3ms) INSERT INTO "things" ("name") VALUES('Jigglymabob') 
Widget Create (0.3ms) INSERT INTO "widgets" ("name", "thing_id") VALUES('Wookeleywoo', 1) 
Thing Load (0.6ms) SELECT * FROM "things" WHERE ("things"."id" = 1 AND (name = 'Jigglymabob')) 

Como estoy tratando y escribiendo esto para usted, me di cuenta Todavía no he dado una respuesta real a tu pregunta. :) Solo puedo pensar en una razón para tener esto en ActiveRecord, y eso se debe a que no fue una molestia extra de implementar, y no hay beneficio en dejarlo.

Alguien por ahí puede estar trabajando en un caso extremo extraña con una base de datos existente, donde la regla de oro en la oficina — que todo el mundo aprende de la manera difícil — es nunca haber un widget Wookeleywoo unido a otra cosa que no sea un Jigglymabob.

+0

Gracias por eso, muy útil. –

Cuestiones relacionadas