开发者

Using structs in Ruby on Rails gives dynamic constant assignment (SyntaxError)

In my controller I have the following simplified code:

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

But Ruby gives the following error:

dynamic constant assig开发者_StackOverflownment (SyntaxError)

on the line marked above.

Which, AFAIK, means that the constant DashItem is already defined. Is this correct? And what to do about it?


The error explains what the problem is - you have a constant being assigned in a context that's too dynamic - i.e. inside the index method.

The solution is to define it outside:

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


If you want to keep the whole thing neatly inside your index method you could do this:

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

As gunn said, you just can't explicitly assign a constant within a method like that...

This solution is explained more in the ruby docs here, second example on the page.


Another simple option here would be to use a local var instead of a constant when assigning and instantiating the Struct in a dynamic setting:

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

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


And if (under circumstances) you start getting warning: redefining constant Struct… when using Lexun's answer then adding a conditional unless Struct::const_defined? 'DashItem' can help.

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

Of course it's important to remember that said warning may be valid and you might be redefining something you don't actually want to redefine. So make sure you know what you're doing before using the above way to silence the warning (and bypass redefining).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜