为什么我的Rails插件中的函数在没有特别要求的情况下无效?

时间:2015-11-11 18:17:28

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord ruby-on-rails-3.2

我的插件需要一些帮助。我想用一个初始化可以在控制器中调用的另一个方法的方法来扩展ActiveRecord::Base

看起来像这样:

class Article < ActiveRecord::Base
    robot_catch :title, :text
    ...
end

我尝试使用ActiveRecord::Base方法扩展robot_catch类似乎如下。该函数将初始化变量中的指定属性(在本例中为:title:text),并使用class_eval使robot?函数可供用户调用控制器:

module Plugin
    module Base
        extend ActiveSupport::Concern

        module ClassMethods
            def robot_catch(*attr)
                @@robot_params = attr

                self.class_eval do
                    def robot?(params_hash)
                        # Input is the params hash, and this function
                        # will check if the some hashed attributes in this hash
                        # correspond to the attribute values as expected,
                        # and return true or false.
                    end
                end
            end
        end
    end
end

ActiveRecord::Base.send :include, Plugin::Base

因此,在控制器中,可以这样做:

class ArticlesController < ApplicationController
    ...
    def create
        @article = Article.new(params[:article])

        if @article.robot? params
            # Do not save this in database, but render
            # the page as if it would have succeeded
            ...
        end
    end
end

我的问题是我是否正确robot_catch是类方法。如上所示,此函数将在模型内部调用。我想知道我是否正在以正确的方式延长ActiveRecord::Baserobot?函数毫无疑问是一种实例方法。

我正在使用Rails 3.2.22,我在另一个项目中将此插件安装为gem,我想使用此功能。

现在,只有在模型中特定require宝石时,它才有效。但是,我希望将功能作为ActiveRecord::Base的一部分包含在内而不需要它,否则我必须在我想要使用它的每个模型中require,而不是特别 DRY 。不应该在Rails启动时将gem自动加载到项目中吗?

编辑:也许回调(http://api.rubyonrails.org/classes/ActiveSupport/Callbacks/ClassMethods.html)可以解决此问题,但我不知道如何使用它。这看起来有点模糊。

2 个答案:

答案 0 :(得分:0)

首先,我建议您确保none of the many many built in Rails validators meet your needs

如果是这样的话,你真正想要的是一个自定义验证器。

构建自定义验证器并不像看起来那么简单,您构建的基本类将具有以下结构:

class SpecialValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    # Fill this with your validation logic
    # Add to record.errors if validation fails
  end
end

然后在你的模型中:

class Article < ActiveRecord::Base
  validates :title, :text, special: true 
end

我会强烈建议确保你想要的东西还没有建成,很有可能。然后使用resources like thisruby guides resources继续关闭自定义验证程序路径。

答案 1 :(得分:0)

答案

我自己找到了解决方案。 Bundler不会从我的项目使用的gemspec中自动加载依赖项,因此我必须在我的应用程序的lib /目录中的engine.rb文件中要求所有第三方gem,以便加载gem。现在一切正常。

第二:robot_catch方法是一种类方法。