关于ruby中常数的澄清

关于ruby中常数的澄清,ruby,constants,Ruby,Constants,我正在尝试构建一个rest客户端,由于很多操作几乎都是相同的,我想我应该将这些操作放入一个模块中,然后扩展该模块以获得这些操作集,并通过将它们定义为常量来保持唯一位的分离,相同的常量,但每个路由的设置不同,因此最终结果是不同的URL,但相同的操作 module Common def list "some_url/#{Route_Name}.json" end end class Posts extend Common Route_Name = '

我正在尝试构建一个rest客户端,由于很多操作几乎都是相同的,我想我应该将这些操作放入一个模块中,然后扩展该模块以获得这些操作集,并通过将它们定义为常量来保持唯一位的分离,相同的常量,但每个路由的设置不同,因此最终结果是不同的URL,但相同的操作

module Common
    def list
        "some_url/#{Route_Name}.json"
    end
end

class Posts
    extend Common
    Route_Name = 'posts'
end

class Comments
    extend Common
    Route_Name = 'comments'
end


Comments.list
#=> "some_url/comments.json"  what I expect to be outputted
但它只是错误,在本例中,它将出错
未初始化常量Common::Route\u Name

我怎样才能让
Route\u Name
成为我期望的样子

编辑:


我通过将
Route\u Name
更改为
@Route\u Name
解决了这个问题,但问题是
Route\u Name
是常量,它永远不会更改,因此使用实例变量感觉不对劲,即使它确实有效。

我做了类似的事情,我定义了几个控制器操作(索引、创建等…)在一个模块中,然后将MyModule包含在我想要使用它们的控制器中

此时,在我的模块中,我可以调用
self.controller\u name
,以了解我的实际来源


因此,您可以使用类似于
self.controller\u Name.tableze
self.class.tableze
的方法来派生路由名称,而不是试图设置
路由名称,在这里我定义了几个控制器操作(索引、创建等)在一个模块中,然后在我想要使用它们的控制器中包含MyModule

此时,在我的模块中,我可以调用
self.controller\u name
,以了解我的实际来源


因此,您可以使用类似于
self.controller\u Name.tableze
self.class.tableze

@Route\u Name
的东西来派生它,而不是试图设置
路由\u Name
,正如您所提到的那样,它是一个实例变量,可以工作,但我认为您实际上要查找的是
@@Route\u Name
,它将请将其设置为类级变量(每个类一个,而不是每个实例)。

@route\u name
正如您所提到的是一个实例变量,可以工作,但我认为您实际要查找的是
@@route\u name
,它将使其成为类级变量(每个类一个,而不是每个实例)

module Common
    def list
        "some_url/#{const_get('Route_Name')}.json"
    end
end

class Posts
    extend Common
    Route_Name = 'posts'
end

class Comments
    extend Common
    Route_Name = 'comments'
end


Comments.list # => "some_url/comments.json"
@mtamhankar在从类名派生路由方面有一个很好的观点


改为使用
const\u get
。这是一个方法调用(与按静态名称查找相比)。这意味着它将从祖先层次结构的底部开始常量查找

module Common
    def list
        "some_url/#{const_get('Route_Name')}.json"
    end
end

class Posts
    extend Common
    Route_Name = 'posts'
end

class Comments
    extend Common
    Route_Name = 'comments'
end


Comments.list # => "some_url/comments.json"
@mtamhankar在从类名派生路由方面有一个很好的观点


ruby方法从该方法的
所有者
中查找常量,而不是从接收方或接收方的类中查找常量。当您访问常量时,ruby解释器会沿着调用模块或类的
模块嵌套查找常量

X = 0

module A
  X = 1

  module B
    p Module.nesting  #=> [A::B, A]

    X = 2

    def self.x
      X
    end
  end
end

A::B.x  # Try commenting out any 'X = ?' to see the difference
当调用
A::B.x
时,ruby尝试在命名空间
A::B
中查找常量
x
(即尝试查找
A::B::x
),如果找到,它将停止查找并立即返回该值。如果未找到,ruby将尝试在
A
中查找
X
,如果仍然没有找到,ruby将尝试在顶级命名空间中查找
X
,即
对象

由于类和模块有一个class/module方法
name
,该方法返回类/模块的名称,因此您可以像下面这样重构
公共
模块:

module Common
  def list
    "some_url/#{name.downcase}.json"
  end
end

并消除所有
Route\u Name='xxx'
ruby方法从该方法的
所有者
查找常量,而不是从接收方或接收方的类。当您访问常量时,ruby解释器会沿着调用模块或类的
模块。嵌套
查找常量

X = 0

module A
  X = 1

  module B
    p Module.nesting  #=> [A::B, A]

    X = 2

    def self.x
      X
    end
  end
end

A::B.x  # Try commenting out any 'X = ?' to see the difference
当调用
A::B.x
时,ruby尝试在命名空间
A::B
中查找常量
x
(即尝试查找
A::B::x
),如果找到,它将停止查找并立即返回该值。如果未找到,ruby将尝试在
A
中查找
X
,如果仍然没有找到,ruby将尝试在顶级命名空间中查找
X
,即
对象

由于类和模块有一个class/module方法
name
,该方法返回类/模块的名称,因此您可以像下面这样重构
公共
模块:

module Common
  def list
    "some_url/#{name.downcase}.json"
  end
end
并首先按名称空间(大致:嵌套它们的位置)然后按祖先(继承的内容)删除所有
Route\u Name='xxx'

Ruby。因为
list
是在
Common
中声明的,所以查找从
Common::Route\u Name
开始,不能再进一步了

但是,当调用
list
时,它会在
Comments
Posts
上被调用,允许您通过
self
访问这些内容。您可以使用
self::Route\u Name
在需要的地方开始查找,而不是让Ruby自己查找常量本身

module Common
  def list
    "some_url/#{self::Route_Name}.json"
  end
end

class Posts
  extend Common
  Route_Name = 'posts'
end

class Comments
  extend Common
  Route_Name = 'comments'
end

puts Comments.list #=> some_url/comments.json
puts Posts.list    #=> some_url/posts.json
Ruby首先按名称空间(大致是:嵌套它们的位置),然后按祖先(继承的内容)。因为
list
是在
Common
中声明的,所以查找从
Common::Route\u Name
开始,不能再进一步

但是,当调用
list
时,它会在
Comments
Posts
上被调用,允许您通过
self
访问这些内容。您可以使用
self::Route\u Name
在需要的地方开始查找,而不是让Ruby自己查找常量本身

module Common
  def list
    "some_url/#{self::Route_Name}.json"
  end
end

class Posts
  extend Common
  Route_Name = 'posts'
end

class Comments
  extend Common
  Route_Name = 'comments'
end

puts Comments.list #=> some_url/comments.json
puts Posts.list    #=> some_url/posts.json
G