定义Rails帮助程序(或非帮助程序)函数,以便在任何地方使用,包括模型

时间:2012-08-07 19:37:31

标签: ruby-on-rails

我有一个执行此操作的功能:

  def blank_to_negative(value)
    value.is_number? ? value : -1
  end

如果传递的值不是数字,则将值转换为-1。

我主要为某个模型创建了这个函数,但是在任何特定模型中定义这个函数似乎都不合适,因为这个函数的应用范围显然可以超出任何一个特定的模型。我几乎肯定需要在其他模型中使用此功能,并且可能在视图中。

定义此功能然后在任何地方使用它的最“Rails Way”方式是什么,特别是在模型中?

我尝试在ApplicationHelper中定义它,但它不起作用:

class UserSkill < ActiveRecord::Base
  include ApplicationHelper
  belongs_to :user
  belongs_to :skill

  def self.splice_levels(current_proficiency_levels, interest_levels)
    Skill.all.reject { |skill| !current_proficiency_levels[skill.id.to_s].is_number? and !interest_levels[skill.id.to_s].is_number? }.collect { |skill| {
      :skill_id => skill.id,
      :current_proficiency_level => blank_to_negative(current_proficiency_levels[skill.id.to_s]),
      :interest_level => blank_to_negative(interest_levels[skill.id.to_s]) }}
  end 
end

那告诉我

  #p>#

的未定义方法`blank_to_negative'

无论如何,我读过you're "never" supposed to do that kind of thing,所以我有点困惑。

4 个答案:

答案 0 :(得分:3)

如果您希望在项目的每个类中都有这样的帮助方法,那么您可以将其作为方法添加到Object或任何您认为合适的方法中 p>

module MyApp
  module CoreExtensions
    module Object
      def blank_to_negative
        self.is_number? ? self : -1
      end
    end
  end
end

Object.send :include, MyApp::CoreExtensions::Object

答案 1 :(得分:2)

有几个选择:

  • 将方法修补到ActiveRecord中,它将在所有模型中使用:

    class ActiveRecord::Base
      def blank_to_negative(value)
        value.is_number? ? value : -1
      end
    end
    
  • 添加一个“关注”模块,然后将其混合到选定的模型中:

    # app/concerns/blank_to_negate.rb
    module BlankToNegate
      def blank_to_negative(value)
        value.is_number? ? value : -1
      end
    end
    
    # app/models/user_skill.rb
    class UserSkill < ActiveRecord::Base
      include BlankToNegate
      # ...
    end
    

答案 2 :(得分:1)

可以扩展Ruby数据类型功能。它们没有密封。由于您希望在所有地方使用它,为什么不扩展FIXNUM功能并向其添加方法blank_to_negative

答案 3 :(得分:0)

这就是我最终做的事情。我将此代码放在config/initializers/string_extensions.rb

class String
  def is_number?
    true if Float(self) rescue false
  end 

  def negative_if_not_numeric
    self.is_number? ? self : -1
  end 
end

此外,我将blank_to_negative重命名为negative_if_not_numeric,因为some_string.negative_if_not_numericsome_string.blank_to_negative更有意义。