【问题标题】:Rails scope with method value comparison具有方法值比较的 Rails 范围
【发布时间】:2016-07-04 12:24:01
【问题描述】:

所以我对 rails 和 ActiveRecord 还很陌生,我需要一个在 Client 实体之间进行过滤的范围。基本上,作用域应该返回所有Client 记录,其中客户端的当前状态等于某个状态对象。

这是通过获取客户端的最后一个state_change 然后拉取state_changefrom_state 来计算的,这是一个State 对象。

我已经定义了一个返回current_state 的方法,但是当我在rails 控制台中使用Client.current_state(Client.last) 对其进行测试时,我得到了这个错误:

NameError: undefined local variable or method 'state_changes for #<Class:0x0000000685eb88> 但在控制台中运行Client.last.state_changes 时它工作正常。

我的客户.rb

class Client < ActiveRecord::Base
  has_and_belongs_to_many               :users
  belongs_to                            :industry
  belongs_to                            :account
  has_many                              :contacts
  has_many                              :state_changes
  belongs_to                            :head,          class_name: "Client"
  has_many                              :branches,      class_name: "Client", foreign_key: "head_id"
  has_many                              :meetings,      through: :contacts
  has_many                              :sales,         through: :meetings

  scope :prospects, -> (client) { where(Client.current_state(client): State.PROSPECT_STATE) }

  def self.has_at_least_one_sale? (client)
    return client.sales.empty?
  end

  def self.has_account_number? (client)
    return client.account_number.present?
  end

  def self.current_state (client)
    state_changes.last.to_state
  end
end

state_change.rb

class StateChange < ActiveRecord::Base
  belongs_to :client
  belongs_to :from_state,   class_name: "State", foreign_key: :to_state_id
  belongs_to :to_state,     class_name: "State", foreign_key: :from_state_id
end

state.rb

class State < ActiveRecord::Base
  has_many :from_states,    class_name: "StateChange", foreign_key: :to_state_id
  has_many :to_states,      class_name: "StateChange", foreign_key: :from_state_id

  def self.PROSPECT_STATE
    return State.find_by name: 'Prospect'
  end

  def self.CLIENT_STATE
    return State.find_by name: 'Client'
  end

  def self.SUSPECT_STATE
    return State.find_by name: 'Suspect'
  end
end

我还收到关于我在 client.rb 中定义的范围的语法错误。我遵循了ActiveRecord 指南,但他们没有解释如何在实际范围查询中使用链接方法。

【问题讨论】:

标签: ruby-on-rails ruby activerecord scope


【解决方案1】:

您收到错误NameError: undefined local variable or method 'state_changes for #&lt;Class:0x0000000685eb88&gt; 的原因是因为您将current_state 定义为类方法并将客户端作为参数传递。这就是为什么在类而不是实例上调用 state_changes 的原因。在这种情况下,您需要使用客户端获取state_changes

def self.current_state (client)
  client.state_changes.last.to_state
end

作用域也只是链接查询逻辑。我不确定是否可以只使用查询来获得您想要的结果。我希望我能正确理解你的逻辑。或者,您可以使用类方法。

def self.prospects (client)
  Client.all.select { |c| c.current_state(c) == State.PROSPECT_STATE }
end

正如Зелёный 在评论中指出的那样,也许您还只想将方法更改为实例方法,在这种情况下阅读他链接的资源会非常有帮助。

根据评论更新:

我认为您真正想要的是使用 current_state 的实例方法,如下所示:

def current_state
  state_changes.last.to_state
end

然后你可以得到这样的前景:

def self.prospects
  Client.all.select { |c| c.current_state == State.PROSPECT_STATE }
end

【讨论】:

  • 感谢您的回答。我不确定我是否理解您为什么想要self.prospects 的参数,这样做的想法是简单地返回每个具有前景状态的客户
  • Client.all.select { |c| Client.current_state(c) == State.PROSPECT_STATE } 是有效的。谢谢!我确实阅读了该资源。
  • @barnacle.m 这会拖累速度,你应该看看查询方法而不是使用rubyselect
猜你喜欢
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 2020-04-30
  • 2017-02-05
  • 1970-01-01
  • 2016-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多