Rails模型使用连接写def

时间:2014-04-08 17:02:25

标签: ruby-on-rails

我正试图在“工作人员”的模型中为“可计费”建立一个def。

关系:

  Workorders - belongs_to :billmethod
  Billmethod - has_many :workorders

我试过这些:

  def self.billable
    joins(:billmethods).where(billmethods: {"method_name != ?", 'Not Billable'})
  end

def self.billable
  where("billmethod.method_name != ?", 'Not Billable')
end

2 个答案:

答案 0 :(得分:3)

您需要使用与has_many / belongs_to中定义的名称相同的名称(但始终使用where()方法中的复数名称:

如果

class Workorder < ActiveRecord::Base    
  belongs_to :billmethod
              #        ^^

,然后

def self.billable
  joins(:billmethod).where('billmethods.method_name != ?', 'Not Billable')
        #         ^^                 
end

如果

class Workorder < ActiveRecord::Base    
  has_many :billmethods
              #       ^

,然后

def self.billable
  joins(:billmethods).where('billmethods.method_name != ?', 'Not Billable')
        #          ^                 
end

答案 1 :(得分:2)

根据您定义的associations

  Workorders - belongs_to :billmethod
  Billmethod - has_many :workorders

模型应该是

class Workorder < ActiveRecord::Base    
  belongs_to :billmethod
  ## Above line specifies the association of model "Billmethod" with "Workorder"
  ## It denotes that a workorder belongs_to a specific billmethod (exactly one) so billmethod must be singular here
  ## ...
end

class Billmethod < ActiveRecord::Base    
  has_many :workorders
  ## Above line specifies the association of model "Workorder" with "Billmethod"
  ## It denotes that a billmethod has_many workorders (0 or more) so workorders must be plural here
  ## ...
end

让我们首先浏览您在Workorder模型中尝试过的代码以及它为什么不起作用:

首次尝试:

  def self.billable
    joins(:billmethods).where(billmethods: {"method_name != ?", 'Not Billable'})
  end

问题1: joins(:billmethods)

如上所述Workorder belongs_to billmethod,因此您必须在此处传递billmethod 单数。否则,ActiveRecord会尝试查找名为billmethods(复数)的关联并引发错误

Association named billmethods was not found on Workorder

问题2: where(billmethods: {"method_name != ?", 'Not Billable'})

{"method_name != ?", 'Not Billable'}应该是Hash类似:{key : value},但看起来{something, something}不是Hash

第二次尝试:

def self.billable
  where("billmethod.method_name != ?", 'Not Billable')
end

问题1: No joining condition

您尚未指定加入条件,因此您无法访问billmethods表中的字段。

问题2: where("billmethod.method_name != ?", 'Not Billable')

您在此处使用了正确的语法。但是,如问题1中所述,即上面的No joining condition,您将无法从method_name表格访问字段billmethods

此处的另一个问题是,在where方法中,您应该使用数据库中存在的实际table name。根据Rails惯例,它将是plural,即billmethods.method_name而不是billmethod.method_name

可能的解决方案:

以下是您可以尝试的几种可能的解决方案:

def self.billable
  joins(:billmethod).where('billmethods.method_name != ?', 'Not Billable')               
end

- 或者 - Rails 4.x

def self.billable
  joins(:billmethod).where.not(billmethods: {method_name: "Not Billable"})               
end

您也可以使用scope而不是类方法:

class Workorder < ActiveRecord::Base    
  belongs_to :billmethod
  scope :billable, ->(status) { joins(:billmethod).where('billmethods.method_name != ?', status)  }
  ## ...
end 

然后您可以将上面定义的范围称为

Workorder.billable("Not Billable")

status将在作用域查询中设置为Not Billable

如果您总是要搜索Not Billable条记录,请将范围更改为:

scope :billable, -> { joins(:billmethod).where("billmethods.method_name != 'Not Billable'")  } 

直接将此范围称为Workorder.billable