1

Sorry, I am still a little green with Ruby on Rails to say the least so I'd appreciate even being guided in the same direction.

So... I have three DB tables, let's call them people, jobs and hats. I have a scope that returns only people that do certain jobs:

named_scope :emergency_workers, :include => :job, :conditions => {'jobs.name' => 'Police', 'jobs.name' => 'Fire','jobs.name' => 'paramedic'}

I have a scope that returns only people that wear a hat:

named_scope :hat_wearers, :include => :job, :joins => :hat, :conditions => ["hats.name IS NOT ?", nil]

My question is, how do I define a scope that says "show me only people that wear a hat (as above) unless they do this particular job, say farmer". So, my code would return all the hat wearers and all the farmers.

Not sure if that makes even a lick of sense but I'd be very grateful for guidance...

4

2 回答 2

2

我不确定如何将其构造为单个查询,但使用 Rails 3 语法,您可以指定给定的范围,然后创建一个方法,从两个范围内的查找中返回唯一结果:

class People < ActiveRecord::Base
  ...
  scope :emergency_workers, joins(:jobs).where('jobs.name IN (?)',['Police','Fire','Paramedic'])
  scope :hat_wearers, joins(:hats).where('hats.name IS NOT ?', nil)
  scope :farmers, joins(:jobs).where('jobs.name= ?', 'farmer')
  ...

  def hats_and_farmers
    result = self.class.hat_wearers + self.class.farmers
    result.uniq
  end
  ...
end

编辑:

我不知道如何编写 SQL 来基于三个表进行查找,但如果您这样做(根据您的评论),只需编写以下代码:

People.find_by_sql('Your custom from scratch query goes here.')

请参阅: http: //guides.rubyonrails.org/active_record_querying.html#finding-by-sql

从模型中调用它所做的只是告诉 Rails 您希望查询返回哪种对象,以便它可以将它们实例化为可供您使用的对象。没有 SQL 是为您预先编写的。

于 2011-08-03T16:38:13.710 回答
0

我建议使用两个单独的命名范围并将它们链接在一起。您可以使用现有hat_wearers范围,还可以定义一个以要排除的作业名称的范围:

named_scope :hat_wearers, :joins => :hat, :conditions => ["hats.name IS NOT ?", nil]
named_scope :without_worker, lambda{|j| :joins  => :job, :conditions => ['jobs.name != ?', j]}

现在您可以将它们链接在一起并person.hat_wearers.without_worker('farmer')单独调用和使用范围。

警告说明:根据您使用的 Rails 版本,使用 :joins 链接作用域可能会变得很棘手。有几个人在网上写过它并在这个网站上询问过它,所以如果你遇到困难,请检查一下。

于 2011-08-03T19:16:58.637 回答