Подтвердить что ты не робот

Использование структур в Ruby on Rails дает динамическое постоянное назначение (SyntaxError)

В моем контроллере у меня есть следующий упрощенный код:

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 уже определена. Это верно? И что с этим делать?

4b9b3361

Ответ 1

Ошибка объясняет, в чем проблема: у вас есть константа, назначенная в слишком динамичном контексте, то есть внутри метода индекса.

Решение состоит в том, чтобы определить его снаружи:

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

Ответ 2

Если вы хотите аккуратно держать все в своем методе индекса, вы можете сделать это:

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 ​​здесь, второй пример на странице.

Ответ 3

И если (при определенных обстоятельствах) вы начнете получать warning: redefining constant Struct… при использовании ответа Lexun добавление условного unless Struct::const_defined? 'DashItem' 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

Конечно, важно помнить, что указанное предупреждение может быть действительным, и вы можете переопределять то, что вы на самом деле не хотите переопределять. Поэтому убедитесь, что вы знаете, что делаете, прежде чем использовать вышеуказанный способ, чтобы заставить замолчать предупреждение (и обойти переопределение).