在Ruby on Rails中使用结构体提供动态常量赋值(SyntaxError)

时间:2011-01-12 15:54:48

标签: ruby struct

在我的控制器中,我有以下简化代码:

def index
  @dashboard_items = []
  DashItem = Struct.new(:name, :amount, :moderated)  # Error is here

  [:page, :post].each do |c|
    obj = c.to_s.capitalize.constantize
    @dashboard_items << DashItem.new(c.to_s, obj.count, obj.count_moderated)
  end
end

但是Ruby给出了以下错误:

  

动态常量赋值(SyntaxError)

在上面标出的行上。

其中,AFAIK,意味着已经定义了常量DashItem。它是否正确?怎么办呢?

4 个答案:

答案 0 :(得分:48)

该错误解释了问题所在 - 您在一个过于动态的上下文中分配了一个常量 - 即在索引方法中。

解决方案是在外面定义:

DashItem = Struct.new(:name, :amount, :moderated)
def index
  @dashboard_items = []
  ...

答案 1 :(得分:13)

如果你想在整个索引方法中整齐地保留整个东西,你可以这样做:

def index
  @dashboard_items = []
  # Set the name of your struct class as the first argument
  Struct.new('DashItem', :name, :amount, :moderated)
  ...
  # Then when you want to create an instance of your structure
  # you can access your class within the Struct class
  @dashboard_items << Struct::DashItem.new(c.to_s, obj.count, obj.moderated)
end

正如gunn所说,你无法在类似的方法中明确地指定一个常量......

此解决方案在页面上的第二个示例ruby docs here中有更多解释。

答案 2 :(得分:0)

如果(在某些情况下)在使用Lexun的答案时开始得到warning: redefining constant Struct…,则添加条件unless Struct::const_defined? 'DashItem'会有所帮助。

def index
  @dashboard_items = []
  # Set the name of your struct class as the first argument
  Struct.new('DashItem', :name, :amount, :moderated) unless Struct::const_defined? 'DashItem'
  ...
  # Then when you want to create an instance of your structure
  # you can access your class within the Struct class
  @dashboard_items << Struct::DashItem.new(c.to_s, obj.count, obj.moderated)
end

当然要记住,警告可能是有效的,并且您可能正在重新定义您实际上不想重新定义的内容,这一点很重要。因此,在使用上述方法使警告静音(并绕过重新定义)之前,请确保您知道自己在做什么。

答案 3 :(得分:0)

这里的另一个简单选择是在动态设置中分配和实例化Struct时,使用局部变量而不是常量:

def index
  # ...
  dash_item = Struct.new(:name, :amount, :moderated)  

  # ...
    @dashboard_items << dash_item.new( ... )
  # ...
end