Rails XML Builder - рефакторинг кода - PullRequest
0 голосов
/ 02 декабря 2009

Я написал следующий код в моем приложении Rails для генерации XML. Я использую Aptana IDE для разработки Rails, и IDE показывает предупреждение о том, что структура кода идентична в обоих блоках. Какие изменения могут быть внесены в код для устранения дублирования в структуре? Есть ли другой способ написать то же самое?

xml.roles do
    @rolesList.each do |r|
        xml.role(:id => r["role_id"], :name => r["role_name"])
    end
end

xml.levels do
    @levelsList.each do |lvl|
        xml.level(:id => lvl["level_id"], :name => lvl["level_name"])
    end
end

Ответы [ 3 ]

1 голос
/ 03 декабря 2009

У меня была идея, похожая на @nathandva, но я правильно использовал send:

def list_to_xml(node_name, list)
  xml.send(node_name.pluralize.to_sym) do 
    list.each do |item|
      xml.send(node_name.to_sym, :id => r["#{node_name}_id"], 
               :name => r["#{node_name}_name"])
    end
  end
end

Поскольку это добавляет визуальную сложность, это изменение может быть не лучшим. Самый большой вопрос: если вы, вероятно, внесете изменения в структуру xml.roles, вы также можете изменить xml.levels? Если это так, обязательно удалите дубликаты. Также важно назвать метод так, чтобы он имел смысл после прочтения; добавьте, что сложность будет уменьшена, а не увеличена.

1 голос
/ 14 июня 2010

У меня была та же проблема с использованием метода send и получением тегов, которые выглядели как <send:id>12</send:id>. Чтобы решить, я использовал «тег!» метод. Поэтому я думаю, что ваш код будет выглядеть так:

def build_xml(node_name, node_list)
  xml.tag!(node_name.pluralize) do
    node_list.each do |node|
      id_str = node["#{node_name}_id"]
      name_str = node["#{node_name}_name"]
      xml.tag!(node_name, :id => id_str, :name => name_str)
    end
  end
end
0 голосов
/ 03 декабря 2009

Как то так?

def build_xml(node_name, node_list)
  xml.send(node_name.pluralize) do
    node_list.each do |node|
      id_str = node["#{node_name}_id"]
      name_str = node["#{node_name}_name"]
      xml.send(node_name, :id => id_str, :name => name_str)
    end
  end
end

build_xml("role", @roleslist)
build_xml("level", @levelslist)

Я пытаюсь использовать send вместо eval [что я плохо сделал: отредактировал, чтобы исправить - спасибо Кэти Ван Стоун].

Редактировать 26/12, потому что построитель xml захватит отправку и использует ее как ветку xml. Существует два возможных варианта, вместо этого используйте метод send , например,

      xml.__send__(node_name, :id => id_str, :name => name_str)

но я не уверен, что он создаст <__send__:roles>. Вы всегда можете вернуться к

      eval("xml.#{node_name} :id => '#{id_str}', :name => '#{name_str}'")

, который обязательно должен работать (но eval всегда следует использовать в крайнем случае).

...