[英]Define class and instance methods dynamically in concern
I have a concern: 我有一个问题:
# app/models/concerns/rolable.rb
module Rolable
extend ActiveSupport::Concern
included do
rolify
Role.find_each do |role|
scope "#{role.name.pluralize}", -> { joins(:roles).where(roles: {name: send("#{role.name}_role_name")}).distinct }
end
end
class_methods do
Role.find_each do |role|
define_method "#{role.name}_role_name" do
role.name
end
define_method "#{role.name}_role_id" do
role.id
end
end
end
Role.find_each do |role|
define_method("#{role.name}?") do
has_role? self.class.send("#{role.name}_role_name")
end
end
end
As you can see it defines a bunch of scopes, class methods and instance methods. 如您所见,它定义了一堆范围,类方法和实例方法。 But I'm not happy about repetition of Role.find_each do |role| ... end
但是我对重复Role.find_each do |role| ... end
感到高兴 Role.find_each do |role| ... end
. Role.find_each do |role| ... end
How can I eliminate this duplication? 我怎样才能消除这种重复? I tried this 我试过这个
Role.find_each do |role|
included do
...
end
class_methods do
...
end
end
But it doesn't work because of multiple included
blocks. 但由于多个included
块,它不起作用。 I can extract Role.find_each
in method, but it's not much better. 我可以在方法中提取Role.find_each
,但它并没有好多少。
How can improve this code and remove duplication? 如何改进此代码并删除重复?
I think you have a bad logic here. 我认为你的逻辑错误。 You shouldn't use Role.find_each
because new roles will not be available after initialize you base class or you will have to load explicitly your concern every time when you need it. 您不应该使用Role.find_each
因为在初始化基类之后新角色将不可用,或者您必须在每次需要时明确加载您的关注点。
In rolify you have useful methods: 在rolify中,您有一些有用的方法:
Forum.with_role(:admin)
Forum.with_role(:admin, current_user)
@user.has_role?(:forum, Forum)
...
If you are pretty sure that your inventory of roles won't expand, then maybe you can dynamically define a bunch of anonymous concerns instead of creating one concern for all roles. 如果您非常确定您的角色库存不会扩展,那么您可以动态定义一堆匿名问题,而不是为所有角色创建一个问题。
# models/concerns/rolables.rb
# no need to call `find_each' because the number or roles will never exceed 1000
Rolables = Role.all.map do |role|
Module.new do
extend ActiveSupport::Concern
included do
scope "#{role.name.pluralize}", -> { joins(:roles).where(roles: {name: send("#{role.name}_role_name")}).distinct }
define_method("#{role.name}?") do
has_role? self.class.send("#{role.name}_role_name")
end
end
class_methods do
define_method "#{role.name}_role_name" do
role.name
end
define_method "#{role.name}_role_id" do
role.id
end
end
end
end
And include all those concerns into your model: 并将所有这些问题包含在您的模型中:
# models/user.rb
class User
Rolables.each{|concern| include concern}
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.