如何使用适用于各种模型的自定义方法

时间:2014-12-16 00:32:30

标签: ruby-on-rails ruby

我有以下方法,名为capitalizeEachWord。在此方法中,有一个名为company

的属性
class BusCompany < ActiveRecord::Base
  attr_accessible :company
  before_save :capitalizeEachWord
  validates :company,presence: true,
                    uniqueness: { case_sensitive: false },
                    format: /^([a-zA-z0-9]+\s?){1,}$/

  def capitalizeEachWord
    self.company=self.company.downcase.split.map(&:capitalize).join(' ')
  end
end

我希望这个方法不直接使用属性公司,但是接受这个属性作为参数,不依赖于模型BusCompany。如下所示。问题是我将在各种模型中使用此方法,并且不希望在每个模型中编写它但使用继承

class BusCompany < ActiveRecord::Base
  attr_accessible :company
  before_save :capitalizeEachWord(self.company)
  validates :company,presence: true,
                       uniqueness: { case_sensitive: false },
                       format: /^([a-zA-z0-9]+\s?){1,}$/

  def capitalizeEachWord(attribute)
    self.attribute=self.attribute.downcase.split.map(&:capitalize).join(' ')
  end
end

2 个答案:

答案 0 :(得分:0)

首先,我建议你覆盖公司的setter而不是使用容易出错的回调,如下所示:

class BusCompany < ActiveRecord::Base
  # you can also use #titleize instead of capitalize each word
  # also use try, in case `arg` is nil
  def company=(arg)
    super arg.try(:titleize)
  end
end

然后,您可以使用模块将此功能包装到可重用的单元中。将其放在您关注的文件夹中的文件中,或者放在models文件夹中:

module CapitalizedSetter
  def capitalize_setter(*attr_names)
    # for each attr name, redifine the setter so it supers the titleized argument instead
    attr_names.each do |attr|
      define_method(:"#{attr}=") { |arg| super arg.try(:titleize) }
    end
  end
end

最后将其扩展为所需的模型:

class BusCompany
  extend CapitalizedSetter

  capitalized_setter :company
end 

答案 1 :(得分:0)

将以下代码添加到config/initializers/capitalizer.rb

module Capitalizer
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def capitalize(*attributes)
      @attributes_to_capitalize = attributes
      before_save :capitalize_each_word
    end

    def attributes_to_capitalize
      Array.new(@attributes_to_capitalize)
    end
  end

  def capitalize_each_word
    self.class.attributes_to_capitalize.each do |attr|
      if value = send(attr)
        self.send("#{attr}=", value.strip.titleize)
      end
    end
  end
end

然后在你的班上:

class BusCompany < ActiveRecord::Base
  include Capitalizer
  capitalize :company

  ...
end