我正在为Rails 4编写一个需要向ApplicationController添加一些方法的gem,我认为最好的方法是编写一个rake任务来打开文件,插入我需要的方法,然后关闭它。最好的方法是什么,以便我的方法在类定义中?
class ApplicationController < ActionController::Base
def existing_methods
foo
end
# insert my methods here
end
修改
在尝试下面的建议后,但无济于事,我尝试了this post,最后尝试了以下内容:
LIB / my_engine.rb
require "my_engine/engine"
require "my_engine/controller_methods"
module MyEngine
end
LIB / my_engine / controller_methods.rb
module MyEngine
module ControllerMethods
extend ActiveSupport::Concern
def foo
"foo"
end
end
end
ActiveRecord::Base.send(:include, MyEngine::ControllerMethods)
运行应用程序时,我的application.slim包含行= foo
,我收到以下错误:
#&lt;#:0x007ff350cd4ba0&gt;
的未定义局部变量或方法`foo'
答案 0 :(得分:3)
好的,我们同意改变主机应用的application_controller.rb是不可取的。让我们看一下通过gem将方法添加到ApplicationController类(实际上是ActionController :: Base)的不同方法。
我创造了一个非常简单的宝石。我希望它添加一个函数rot13,这意味着任何控制器都可以调用rot13('something!')
来获取'fbzrguvat!'
。
(在现实生活中,您将此添加到String
...)
你可以扩展ActionController::Base
,如下所示:
class ActionController::Base
def rot13 str
a = 'a'.ord
z = 'z'.ord
str.unpack('c*').map { |x| (a..z).cover?(x) ? (((x - a) + 13) % 26) + a : x }.pack('c*')
end
end
现在在我的应用程序中,我可以在任何控制器和rot13('ibvyn!')
voila!
添加模块并通过Railtie挂钩将其包含在ActionController :: Base中更安全。所以,让我们添加一个Railtie。
我添加lib/rot13/railtie.rb
如下:
module Rot13
class Rot13Railtie < Rails::Railtie
initializer "rot_13_railtie.extend_action_controller" do
ActiveSupport.on_load :action_controller do
# At this point, self == ActionController::Base
include Rot13::ControllerMethods
end
end
end
end
现在lib/rot13.rb
看起来像这样:
require "rot13/version"
require "rot13/railtie.rb" if defined? Rails
module Rot13
module ControllerMethods
def rot13 str
a = 'a'.ord
z = 'z'.ord
str.unpack('c*').map { |x| (a..z).cover?(x) ? (((x - a) + 13) % 26) + a : x }.pack('c*')
end
end
end
这适用于大多数用途。
我们假设您不希望rot13
方法在ActionController::Base
中定义并且可供所有控制人使用 - 让我们说您想要用户宝石来选择加入&#39;在逐个控制器的基础上,例如
class ApplicationController < ActionController::Base
with_rot_13
# and so on...
end
您可以在include Rot13::ControllerMethods
块中调用extend Rot13::ControllerOptIn
而不是on_load
,而是在with_rot_13
的类级添加ActionController::Base
方法,然后定义{ {1}}模块如下:
ControllerOptIn
那就是它!
修改:只是为了解决“为什么我的视图中无法看到该方法”的其他问题?&#39; - 您的方法未定义为帮助程序,因此在视图中不会自动显示,而不会使用module Rot13
module ControllerMethods
# ...
end
module ControllerOptIn
def with_rot_13
include ControllerMethods
end
end
end
加上后缀,例如controller
。幸运的是,您可以通过调用%p= controller.rot13 'blah'
将其定义为帮助者,例如
helper_method
现在你可以这样做(注:HAML):
module ControllerOptIn
def with_rot_13
include ControllerMethods
helper_method :rot13
end
end
但是在这里指定%p= controller.rot13 'hello there!'
%p= rot13 'well how are ya?'
并不是很好。你能直接从helper_method :rot13
挖出必要的符号吗?当然,只要你确定它是你想要的:
Rot13::ControllerMethods