finder_sql для отношения has_many - PullRequest
1 голос
/ 10 февраля 2009

Учитывая следующие две (упрощенные) модели:

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

Сначала кажется, что это работает нормально:

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

Но когда я пытаюсь следовать, я получаю ошибку mysql:

>> Customer.first.users.find_by_email("test@example.com")
ActiveRecord::StatementInvalid: Mysql::Error: Operand should contain 1 column(s): 
SELECT * FROM `users` 
WHERE (`users`.`email` = 'test@example.com') 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'

Итак, Rails генерирует недопустимый оператор SQL. Причиной этого, вероятно, является мой finder_sql, потому что ассоциация без finder_sql работает как положено.

Я уже пытался удалить все дополнительные плагины (will_paginate). То, чего я пытаюсь добиться, на самом деле довольно просто: включите в свою ассоциацию все пользовательские модели, соответствующие следующему условию (users.customer_id = 1 OR users.customer_id IS NULL).

Ценю любую помощь!

Ответы [ 2 ]

3 голосов
/ 10 февраля 2009

Возможно, вам будет проще, если у вас есть специальный «глобальный» клиент, поэтому вам не нужно иметь дело с неловкостью NULL.

Это пример использования шаблона Null Object .

1 голос
/ 10 февраля 2009

Любой из них должен работать

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

или

Customer.first.users.select{|user| user.email == "test@example.com"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...