类变量和模块包含,特别是在 ActionController 中
我想要某种在单独的模块中初始化的单个列表,然后可以包含在控制器中并在控制器类级别进行修改,并在控制器实例级别进行访问。我认为类变量在这里可以工作,但是奇怪的事情发生了,它们似乎没有在我的结束类中初始化。
更具体地说:
我有许多控制器,都在模块中包含一些默认功能。
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 是一个错误的调用,但我想不出我还可以使用什么。 (类实例变量?)
I want to have some kind of single list that is initialized in a seperate module, then can be included in a controller and modified at the controller-class level, and accessed at the controller-instance level. I thought class variables would work here, but something strange is happening, they don't seem to be being initialized within my ending class.
More specifically:
I have many controllers all including some default functionality, in a module.
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
, for instance. This isn't the actual code, but that's the most interaction it has at the moment.
I'd like to extend this with some other functionality (a sortable interface for lists,) like so [note I'd like to be able to swap out the sort-order-list functionality on a class by class basis]:
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
The idea is to make sure that I'm able to swap out the set of all possible sorts on a class by class basis, like so:
class FooController < ApplicationController
include DefaultFunctionality #calls the default set_sorts
set_sorts([{:order => :most_recent, :sort_direction => :asc}])
end
And also to make nice links in the views, like below, except that I'm getting an error.
___/blah/1 => shared/show.html.erb__
<%= link_to("upside down", polymorphic_path(model, sort_params) %><%#BOOOM uninitialized class variable @@sorts for BlahController %>
I figure the class_var is a bad call, but I can't think of what else I might use. (a class instance var?)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
当然,类实例变量是正确的选择。您实际上很少需要使用类变量。
在具体回答您的问题时,请记住,模块中定义的任何代码仅在加载模块时执行一次,而不是在包含模块时执行。这种区别可能并不明显,特别是当人们认为“include”等同于“require”时。
您需要的是:
捕获包含模块的类的方法是相应地定义 Module.included 。在这种情况下,每次包含此模块时都会调用 set_sorts,并且它位于调用类的上下文中。
我对此进行了一些修改,以包括一些特定的样式更改:
Class instance vars are the way to go, for sure. Rarely do you actually need to use a class variable.
In specific answer to your problem, keep in mind that any code defined in your module is executed only once when the module is loaded not when the module is included. This distinction may not be obvious, especially when people consider "include" to be equivalent to "require".
What you need is this:
The way you catch a class including your module is to define Module.included accordingly. In this case, set_sorts is called each time this module is included, and it is in the context of the calling class.
I've modified this a bit to include a few specific style changes:
您必须向模块添加一个
included
方法才能使其工作。You have to add a
included
method to your module for this to work.在注意到 @tadman 做出响应之前,我最终使用了类级实例变量和 Include() ,没有自动包含子模块。
它最终看起来像这样:
在控制器中,在 /lib
lib/default_controller_functionity.rb
lib/default_controller_functionity/sortable.rb下
I ended up using a class level instance variable and included() with no autoincluded submodules, before noticing that @tadman had responded.
It ended up looking like this:
in the controllers, and under /lib
lib/default_controller_functionality.rb
lib/default_controller_functionality/sortable.rb