2009-02-10 8 views
1

Compte tenu des deux modèles (simplifié) suivants:finder_sql pour la relation has_many

class Customer < ActiveRecord::Base 
    # finder sql to include global users in the association 
    has_many :users, :dependent => :destroy, 
    :finder_sql => 'SELECT `u`.* FROM `users` `u` 
    WHERE (`u`.`customer_id` = "#{id}" OR `u`.`customer_id` IS NULL)' 

    validates_presence_of :name 
end 

class User < ActiveRecord::Base 
    # most users belong to a customer. 
    # however, the customer_id may be NULL 
    # to implement the concept of "global" users. 
    belongs_to :customer 
    validates_presence_of :email 
end 

Au début, cela semble fonctionner très bien:

>> Customer.first.users # => Array of users including global users 

Mais quand j'essayer de suivre je reçois une erreur mysql :

>> Customer.first.users.find_by_email("[email protected]") 
ActiveRecord::StatementInvalid: Mysql::Error: Operand should contain 1 column(s): 
SELECT * FROM `users` 
WHERE (`users`.`email` = '[email protected]') AND 
(
    SELECT `u`.* FROM `users` `u` 
    WHERE (`u`.`customer_id` = "1" OR `u`.`customer_id` IS NULL) 
    ORDER BY u.nickname 
) LIMIT 1 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract_adapter.rb:188:in `log' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/mysql_adapter.rb:309:in `execute' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/mysql_adapter.rb:563:in `select' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all_without_query_cache' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/query_cache.rb:62:in `select_all' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:635:in `find_by_sql' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1490:in `find_every' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1452:in `find_initial' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:587:in `find' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1812:in `find_by_email' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1800:in `send' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:1800:in `method_missing' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:370:in `send' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:370:in `method_missing' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/base.rb:2003:in `with_scope' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in `send' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_proxy.rb:202:in `with_scope' 
from /Library/Ruby/Gems/1.8/gems/activerecord-2.2.2/lib/active_record/associations/association_collection.rb:366:in `method_missing' 

Ainsi, Rails génère une instruction SQL non valide. La raison en est probablement mon finder_sql, car l'association sans finder_sql fonctionne comme prévu.

J'ai déjà essayé d'enlever tous les plugins optionnels (will_paginate). La chose que j'essaie de réaliser est en fait assez simple: Inclure tous les modèles d'utilisateur correspondant à la condition suivante: (users.customer_id = 1 OR users.customer_id IS NULL) dans mon association.

Appréciez toute aide!

Répondre

1

Chacune de ces devrait fonctionner

User.find(:all, :conditions => ['customer_id = ? OR customer_id IS NULL', Customer.first[:id]]) 

ou

Customer.first.users.select{|user| user.email == "[email protected]"} 
3

Vous pourriez trouver plus facile si vous avez réellement un client « global » spécial afin que vous n'avez pas besoin de traiter les maladresses de la NULL. Il s'agit d'un exemple d'utilisation de Null Object pattern.

Questions connexes