如何动态地限定命名空间类的名称?

时间:2014-10-08 01:06:07

标签: ruby

有关红宝石的信息:http://coderrr.wordpress.com/2008/03/11/constant-name-resolution-in-ruby/

不能帮助我解决我的问题..但它至少解释了他们'为什么'


我写了以下方法:

# delegate to a user permission serializer specific to the given object
# - if a serializer is not found for the given object, check the superclass
#
# @raise [NameError] if none of object, or it's superclasses have a known
#   user permission serializer
# @return [UserPermission::*Serializer] returns serialized object
def self.serialized_for(object, user, klass: nil, recursion_limit: 5)
    object_class = klass ? klass : object.class
    # use demodulize to chop off the namespace and get the generic object name
    object_name = object_class.name.demodulize
    # bulid serializer name
    name = "::UserPermission::#{object_name}Serializer"

    begin
        binding.pry
        permissions = object.user_permissions(user)
        return name.constantize.new(permissions)
    rescue NameError => e
        raise e if recursion_limit < 1
        # try with super class
        UserPermission.serialized_for(
            object,
            user,
            klass: object_class.superclass,
            recursion_limit: recursion_limit - 1
        )
    end
end

目标是能够检索任何子类的序列化程序,前提是子类具有已定义的序列化程序的超类。 (我正在使用ActiveModelSerializers,但这在这里并不重要。)

我的问题是我在name.constantize运行时收到一个非命名空间的类。

我现有的课程:

  • UserPermission
  • UserPermission :: ProposalSerializer
  • PresentationSerializer&lt; ::加载ActiveModel串行
  • 演示&lt;提案
  • 提案&lt;的ActiveRecord ::基

我期待发生的事情是,当我使用UserPermission.serialized_for致电Presentation时,name.constantize尝试给我一个::UserPermission::PresentationSerializer,然后抛出一个NameError因为班级不存在。

我得到的是::PresentationSerializer,这是不好的 - 用于不同的目的。

以下是我在irb中复制问题的方法: (也许上面的上下文对此有一个过于复杂的解释):

class NameSpace; end
class NameSpace::Klass; end
class Klass; end
class SubKlass < Klass; end
Object.const_get "::NameSpace::SubKlass"
=> SubKlass
Object.const_get("::NameSpace").const_get("SubKlass")
=> SubKlass
eval("NameSpace::SubKlass")
(eval):1: warning: toplevel constant SubKlass referenced by NameSpace::SubKlass
=> SubKlass

有没有办法可以对"::NameSpace::SubKlass"进行限定,以便因NameSpace::SubKlass不存在而导致NameError?

P.S。:我希望上下文有所帮助。


编辑:发现了另一个问题:

UserPermission::Template < UserPermission::Proposal
UserPermission::Template.superclass
=> Proposal

应为UserPermission::Proposal

UserPermission::Proposal
(pry):9: warning: toplevel constant Proposal referenced by UserPermission::Proposal
=> Proposal

UserPermission::Proposal是一个班级。所以......这是一个大问题。 o.o

我正在使用Ruby 2.1.0

1 个答案:

答案 0 :(得分:1)

不要以简洁的方式定义您的类和模块。你遇到了范围问题。

module UserPermission
  class Proposal
  end  
end  

module UserPermission
  class Template < Proposal
  end  
end

UserPermission::Template.superclass
# => UserPermission::Proposal