在Ruby on Rails应用程序中随处调用方法

时间:2011-07-28 05:09:58

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

我正在使用Ruby on Rails 3.0.9,我试图从内部帮助器,控制器,模型和视图文件中调用一些方法。我想要做的是创建一个库,在我的应用程序内部构建\ standardize命名约定,以便我可以使用\运行如下所示:

standardized_name = standardize_name(Article)

您有什么建议?

P.S。:我听说过mixin,但我应该如何在我的情况下使用它们?此外,我不想在每个需要使用它的类中声明包含mixin(也就是说,我希望在我的所有应用程序类中都包含一个包含mixin的“唯一”语句。)

2 个答案:

答案 0 :(得分:6)

可以在Rails MVC的所有层中访问的类似库是I18n。您可以使用I18n.t调用translate方法,而视图和控制器层中有一个辅助方法,因此您不需要每次都输入整个“I18n.t”。

我们可以遵循I18n的做法。您可以在应用程序的lib目录中创建一个模块。确保更新application.rb以便加载模块。在application.rb中查找此评论:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)

显然,如果您取消注释autoload_paths行,请将“extras”更改为“lib”。

这是一个示例模块lib / Karate.rb:

module Karate
  class << self
    def punch(grunt)
      puts "#{grunt}! *punch*"
    end
  end
end

现在您可以在应用程序的任何位置调用它:

Karate.punch("boom")
# => boom! *punch*

如果您想在View和Controller层中使用辅助方法,只需在application_controller.rb中添加一个方法:

def punch(grunt)
  Karate.punch(grunt)
end

并将此方法声明为辅助方法(也在application_controller.rb中),如下所示:

helper_method :punch

但是请确保你真的需要这个库。我没有质疑你的理由,因为它不会回答你的主要问题。我认为您应该在代码中练习您的命名约定,如果必须,请将其添加到README中,或者向您的团队发送电子邮件。此外,Rails和Ruby已经有了命名约定,所以一定要了解它。

答案 1 :(得分:4)

根据您的使用情况,您可以采用其中一种方法,而不是将方法附加到其作用于的对象上。那么您不需要在任何想要使用它的地方都包含standardize_name方法;你只需将它集中在它适用的对象上:

用作Article.standardized_name(类方法):

如果您的standardize_name方法仅将ActiveRecord模型作为参数,请考虑将其放在模块中(例如在lib/standardizable.rb中)并将其扩展到ActiveRecord::Base(或其他一些类)所有域类的父级):

module Standardizable
  def standardized_name
    # in here, self will be the model *class*,
    # so the following will return "Article" if you
    # extended the module into the Article class:
    self.name
  end
end

# include the mixin in all ActiveRecord models:
ActiveRecord::Base.extend Standardizable

或者,如果您不想将其包含在所有模型中,只需将模块包含在您希望standardized_name可用的各个类中:

class Article < ActiveRecord::Base
  extend Standardizable
end

使用以下两种方法,您将能够使用如下方法:

standardized_name = Article.standardized_name

用作Article.new.standardized_name(实例方法):

如果您更愿意在模型类的实例上使用该方法,只需将上例中的extend更改为include

module Standardizable
  def standardized_name
    # in here, self will be the model object *instance*,
    # so the following will return "Article" if you
    # included the module into the Article class:
    self.class.name
  end
end

# include the mixin in all ActiveRecord models:
ActiveRecord::Base.send(:include, Standardizable)

然后用法如下:

article = Article.new

standardized_name = article.standardized_name

结束使用ActiveSupport ::关注:

在Rails 3中包含这两种方法的好方法是使用ActiveSupport::Concern

module Standardizable
  extend ActiveSupport::Concern

  module ClassMethods
    def standardized_name
      self.name
    end
  end

  module InstanceMethods
    def standardized_name
      self.class.standardized_name
    end
  end
end

ActiveRecord::Base.extend Standardizable

然后,您可以使用class和instance方法获取标准化名称:

standardized_name_from_class = Article.standardized_name
article = Article.new
standardized_name_from_instance = article.standardized_name