我为从gem(Spree)继承的控制器添加以下覆盖:
module Spree
module Admin
UsersController.class_eval do
def index
if params[:role].present?
included_users = Spree::User.joins(:role_users).
where( spree_role_users: { role_id: params[:role] } ).map(&:id)
flash[:notice] = "Filtered in #{included_users.count} users"
@users = @users.where(id: included_users)
end
end
end
end
end
基本上,它通过Admin::UsersController
控制器上的附加参数进行过滤。 gem中该控制器的源实际上并没有定义index
方法,所以我只是调用它。
现在,这在开发中非常有效。但是,在生产中,这种方法永远不会被调用。
我有没有关于class_eval
的某些内容我没有来这里?这样的事情不应该像开发中那样在生产中基本相同吗?
感谢您的帮助。
答案 0 :(得分:1)
装饰器是包装另一个对象的对象。例如,它们通常用于包含具有表示逻辑的模型。
class_eval
这不是装饰器方法 - 您只是重新打开类并添加方法。这称为monkey-patching。
在这种情况下,使用module Spree
module Admin
class UsersController
def index
if params[:role].present?
included_users = Spree::User.joins(:role_users).
where( spree_role_users: { role_id: params[:role] } ).map(&:id)
flash[:notice] = "Filtered in #{included_users.count} users"
@users = @users.where(id: included_users)
end
end
end
end
end
与使用class关键字完全相同:
/app
使用monkey-patches,关键是确保读取类重新定义。我猜测开发和生产之间的区别是由于类捕获,如果已经由Spree gem定义了类,则会阻止从config/application.rb
读取类。 config/initializers
使用bundler在应用程序启动时需要所有gem。
您可以通过将猴子补丁放入class MyUsersController < ::Spree::Admin::UsersController
def index
if params[:role].present?
included_users = Spree::User.joins(:role_users).
where( spree_role_users: { role_id: params[:role] } ).map(&:id)
flash[:notice] = "Filtered in #{included_users.count} users"
@users = @users.where(id: included_users)
end
end
end
来确保加载猴子补丁,因为该目录中的所有文件都是在启动时加载的。
但是monkeypatching的一个更好的替代方法可能是将供应商控制器和route子类化为它:
var articles= {
"item1":{
"id":"155",
"name":"First Item",
"value":-5199.6
},
"item2":{
"id":"255",
"name":"Second Item",
"value":-424.91
}
}
var ids = [];
for(var item in articles) {
ids.push(articles[item]['id']);
}
console.log(ids);