【问题标题】:Calling methods everywhere in a Ruby on Rails application在 Ruby on Rails 应用程序中到处调用方法
【发布时间】:2011-10-14 19:47:24
【问题描述】:

我正在使用 Ruby on Rails 3.0.9,并且我试图让从所有内部帮助器、控制器、模型和视图文件中调用一些方法成为可能。我想做的是创建一个库来在我的应用程序内部构建\标准化命名约定,以便我可以使用\运行类似以下内容:

standardized_name = standardize_name(Article)

你有什么建议?

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

【问题讨论】:

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


    【解决方案1】:

    在 Rails MVC 的所有层都可以访问的类似库是 I18n。您可以使用 I18n.t 调用 translate 方法,而视图和控制器层中有一个 helper t 方法,因此您无需每次都输入整个“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*
    

    如果你想在你的视图和控制器层中添加一个辅助方法,只需在 application_controller.rb 中添加一个方法:

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

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

    helper_method :punch
    

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

    【讨论】:

      【解决方案2】:

      根据您的用例,您可以采用其中一种方法来将方法附加到它所作用的对象上。那么你不需要在任何你想使用它的地方都包含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(实例方法):

      如果您希望在模型类的instances 上使用该方法,只需将上面示例中的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::Concern:

      在 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
      

      那么你可以同时使用类和实例方法来获取标准化的名称:

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

      【讨论】:

      • 如果我想扩展所有类(也是 String 类)以同时运行 'Article.standardized_name' 和 '"Some_string".standardized_name'?
      • 那么就这样做:Object.extend(Standardizable)。但是不建议这样做:这意味着您的模块需要能够处理任何可以想象的类型,并且您会污染全局命名空间。不过,仅扩展 String 类是相当普遍的,并且由 e.g. 广泛完成。主动支持。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 2011-05-15
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多