Использование структур в Ruby on Rails дает динамическое назначение констант (SyntaxError) - PullRequest
24 голосов
/ 12 января 2011

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

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

Ответы [ 3 ]

48 голосов
/ 12 января 2011

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

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

DashItem = Struct.new(:name, :amount, :moderated)
def index
  @dashboard_items = []
  ...
13 голосов
/ 11 апреля 2013

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

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

Как сказал Ганн, вы просто не можете явно назначить константу внутри такого метода ...

Это решение более подробно описано в документации по ruby ​​ здесь , второй пример на странице.

0 голосов
/ 06 июля 2019

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...