我希望在单独的模块中初始化某种单一列表,然后可以将其包含在控制器中并在控制器级别进行修改,并在控制器实例级别进行访问。我认为类变量可以在这里工作,但是发生了一些奇怪的事情,它们似乎没有在我的结束类中初始化。
更具体地说:
我在模块中有许多控制器,包括一些默认功能。
class BlahController < ApplicationController
include DefaultFunctionality
end
class FooController < ApplicationController
include DefaultFunctionality
end
module DefaultFunctionality
def show
render 'shared/show'
end
def model
controller_name
end
end
例如,。这不是实际的代码,但这是目前最多的互动。
我想用一些其他功能(列表的可排序接口)来扩展它,就像这样[注意我希望能够逐个类地交换排序顺序列表功能] :
module DefaultFunctionality
module Sortable
def sort_params
params.slice(:order, :sort_direction).reverse_merge(default_sort_params)
end
def default_sort_params
@@sorts.first
end
def set_sorts(sorts = []) #sorts = [{:order => "most_recent", :sort_direction => :desc},...]
@@sorts = sorts
end
end
include Sortable
set_sorts([{:order => :alphabetical, :sort_direction => :asc}] #never run?
end
我的想法是确保我能够逐个类地换出所有可能排序的集合,如下所示:
class FooController < ApplicationController
include DefaultFunctionality #calls the default set_sorts
set_sorts([{:order => :most_recent, :sort_direction => :asc}])
end
并且在视图中制作好的链接,如下所示,除了我收到错误。
___/blah/1 => shared/show.html.erb__
<%= link_to("upside down", polymorphic_path(model, sort_params) %><%#BOOOM uninitialized class variable @@sorts for BlahController %>
我认为class_var是一个糟糕的调用,但我想不出我还能使用什么。 (类实例var?)
答案 0 :(得分:2)
类实例变量是可行的方法,当然。您实际上很少需要使用类变量。
在具体回答您的问题时,请记住,模块中定义的任何代码只能在模块加载时执行而不是在包含模块时执行。这种区别可能并不明显,特别是当人们认为“包含”等同于“要求”时。
你需要的是:
module DefaultFunctionality
def sort_params
params.slice(:order, :sort_direction).reverse_merge(default_sort_params)
end
def default_sort_params
@sorts.first
end
def sorts=(sorts = nil)
@sorts = sorts || [{:order => "most_recent", :sort_direction => :desc}]
end
def self.included(base_class)
self.sorts = ([{:order => :alphabetical, :sort_direction => :asc}]
end
end
您捕获包含模块的类的方法是相应地定义Module.included。在这种情况下,每次包含此模块时都会调用set_sorts,并且它位于调用类的上下文中。
我对此进行了一些修改,以包含一些特定的样式更改:
答案 1 :(得分:0)
您必须在模块中添加included
方法才能实现此目的。
module DefaultFunctionality
def self.included(base)
base.include(Sortable)
set_sorts([{:order => :alphabetical, :sort_direction => :asc}] #never run?
end
module Sortable
# other methods
def set_sorts(sorts = [{:order => "most_recent", :sort_direction => :desc}])
@@sorts = sorts
end
end
end
答案 2 :(得分:0)
在注意到@tadman已经响应之前,我最终使用了一个类级实例变量并且include()没有自动包含的子模块。
最终看起来像这样:
class BlahController < ApplicationController
include DefaultControllerFunctionality
include DefaultControllerFunctionality::Sortable
end
class FooController < ApplicationController
include DefaultControllerFunctionality
include DefaultControllerFunctionality::Sortable
sorts=([{:order => :most_recent, :sort_direction => :desc}])
end
在控制器中,在/ lib下
<强> LIB / default_controller_functionality.rb 强>
module DefaultFunctionality
def show
render 'shared/show'
end
def model
controller_name
end
end
lib / default_controller_functionality / sortable.rb
module DefaultControllerFunctionality
module Sortable
def self.included(base)
base.helper_method :sort_params
base.class_eval <<-END
@sorts=[]
class << self; attr_accessor :sorts end
END
#this line ^ makes it so that the module
#doesn't work when included in any other
#module than the class you want @sorts to end up in.
#So don't include(Sortable) in DefaultControllerFunctionality and expect .sorts to work in FooController.
base.sorts= [{:order => :alphabetical, :sort_direction => :asc}]
end
def sort_params
params.slice(:order, :sort_direction).reverse_merge(default_sort_params)
end
def default_sort_params
self.class.sorts.first
end
end
end