简单的范围和关联

时间:2014-03-12 10:19:32

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-4

所以我对范围很陌生,并且不太了解它们。我们说我有2个模型,ProjectTicket

class Project < ActiveRecord::Base
 has_many :tickets
end

class Ticket < ActiveRecord::Base
 belongs_to :project
end

我习惯这样编码来访问门票中的相关数据:

Project.find(1).tickets.each do |ticket|
 puts ticket.name
end

我创建了新范围:

scope :default, -> { where(default: true) }

现在当我使用Project.default时,我会回来ActiveRecord::Relation并且不知道如何访问关联的tickets

3 个答案:

答案 0 :(得分:2)

Project.default确实会返回ActiveRecord::Relation,这是一个'待触发'查询。一旦你开始循环等,就会触发查询,这对你来说是透明的。

如果您想从项目中获取门票,首先我建议您将它们包含在您的查询中,以避免N + 1。这样做:

projects = Project.default.includes(:tickets)

然后访问特定项目的门票:

project = projects.first
project.tickets 

如果希望方法始终返回单个对象:

class Project < ActiveRecord::Base
  has_many :tickets

  def self.get_default_with_tickets
    Project.where(default: true).includes(:tickets).first
  end
end

然后:

Project.get_default_with_tickets #=> your_project

务必处理案件:

  • 当有多个比赛时
  • 没有匹配时

答案 1 :(得分:0)

scope基本上只是一个class method(在非初始化模型上触发的一个):

class Project < ActiveRecord::Base
 has_many :tickets
 scope :defaults, -> { where(default: true) }
end

这意味着如果你这样做:

@defaults = Project.defaults

...您将所有project个对象恢复为具有属性default为真的

这与此相同:

class Project < ActiveRecord::Base
 has_many :tickets
 def self.defaults
      where(default: true)
 end
end

错误

你获得关系的原因是因为当你使用where时,你基本上得到了一个“数组”数据(而不是只有一个记录)。如果您.each通过数据或只返回.first,您将获得一个可以输出的实际对象:

@defaults = Project.defaults
@defaults.each do |project|
    project.tickets #-> associated tickets
end

答案 2 :(得分:0)

使用allfirst完成查询。

#get all default projects
Project.default.all 

#get the first default project
Project.default.first