Nokogiri XML-канал подачи организации? - PullRequest
1 голос
/ 19 февраля 2011

Я создал сайт, основанный на XML-фиде, который я сейчас анализирую с Nokogiri. Все работает хорошо и прекрасно, хотя у меня есть весь код в настоящее время в моем контроллере администратора, так что я могу фактически вызвать импорт через URL, т.е.

Я не могу не думать, что это не относится к контроллеру. Есть ли лучший способ сделать это, то есть переместить код в отдельный файл import.rb, чтобы он был доступен только из консоли? Если да, то куда мне нужно поместить этот файл, в каталог /lib/?

Вот фрагмент кода:

class AdminController < ApplicationController

    def import
      f = File.open("#{Rails.root}/public/feed.xml")
      @doc = Nokogiri::XML(f)
      f.close

      ignore_list = [] # ignore list

      @doc.xpath("/*/product[not(name = following-sibling::product/name)]").each do |node|
        if !ignore_list.include? node.xpath("./programName").inner_text.strip
          Product.create(:name => clean_field(node.xpath("./name").inner_text).downcase, 
          :description => clean_field(node.xpath("./description").inner_text),
          :brand => Brand.find_or_create_by_name(clean_field_key(node.xpath("./brand").inner_text).downcase),         
          :merchant => Merchant.find_or_create_by_name(clean_field_key(node.xpath("./programName").inner_text).downcase),     
          :image => node.xpath("./imageUrl").inner_text.strip,
          :link => node.xpath("./productUrl").inner_text.strip,
          :category => Category.find_or_create_by_name(clean_field_key(node.xpath("./CategoryName").inner_text).downcase),
          :price => "£" + node.xpath("./price").inner_text.strip)
          print clean_field(node.xpath("./name").inner_text).downcase + "\n"       
        end
      end
    end
end

Ответы [ 2 ]

4 голосов
/ 19 февраля 2011

Ваш код звучит так, как будто он хорошо работает, будучи запущенным как скрипт для запуска Rails.Это скрипты, которые запускаются за пределами обычного процесса Rails для вашего сайта, но имеют полный доступ к настройке ActiveRecord, так что вы можете легко получить доступ к вашей базе данных.

Я не думаю, что Rails столь же строг в отношении файлаlocation, как и для всех остальных файлов, но я бы создал подкаталог в «app» под названием «scripts» и поместил его туда.Поддержание аккуратной структуры каталогов - хорошая вещь для обслуживания.

Вы не говорите, используете ли вы Rails 3 или предыдущую версию.Если вы используете Rails 3, введите rails runner -h в командной строке вашего приложения Rails для получения дополнительной информации.

Некоторые люди считают, что сценарии должны запускаться с использованием rake, с чем я согласен ЕСЛИ они управляют файлами и папками и выполняют общее обслуживание пространства направляющих, в котором работает ваше приложение. Есливы выполняете периодическое задание, которое является частью ведения базы данных, или, в вашем случае, извлекаете контент, используемый для поддержки вашего приложения, я думаю, что это должно быть заданием "бегуна".

Вы можете создать функциональность, чтобы запускать код по URL-адресу, но я думаю, что есть вероятность злоупотребления этим, особенно если вы можете перезаписать необходимые данные или заполнить базу данных дубликатами / избыточными данными.Я думаю, что было бы лучше, чтобы задача запускалась периодически, возможно, через cron, инициированный ОС, просто для того, чтобы поддерживать хороший интервал или запускаться только вручную.Если вы сохраните его доступным через URL-адрес, я бы порекомендовал использовать пароль, чтобы избежать злоупотреблений.

Наконец, как человек, который делал это долгое время, я бы порекомендовал немного структуры и выравнивания в вашемcode:

Product.create(
  :name        => clean_field(node.xpath("./name").inner_text).downcase,
  :description => clean_field(node.xpath("./description").inner_text),
  :brand       => Brand.find_or_create_by_name(clean_field_key(node.xpath("./brand").inner_text).downcase),
  :merchant    => Merchant.find_or_create_by_name(clean_field_key(node.xpath("./programName").inner_text).downcase),
  :image       => node.xpath("./imageUrl").inner_text.strip,
  :link        => node.xpath("./productUrl").inner_text.strip,
  :category    => Category.find_or_create_by_name(clean_field_key(node.xpath("./CategoryName").inner_text).downcase),
  :price       => "£" + node.xpath("./price").inner_text.strip
)

Простое выравнивание может иметь большое значение, чтобы помочь вам поддерживать ваш код или сохранить здравомыслие того, кто его поддерживает.Я бы, наверное, продолжал выглядеть так:

Product.create(
  :name        => clean_field( node.xpath( "./name"        ).inner_text ).downcase,
  :description => clean_field( node.xpath( "./description" ).inner_text ),

  :brand       => Brand.find_or_create_by_name(    clean_field_key( node.xpath( "./brand"       ).inner_text ).downcase ),
  :merchant    => Merchant.find_or_create_by_name( clean_field_key( node.xpath( "./programName" ).inner_text ).downcase ),

  :image       => node.xpath( "./imageUrl"   ).inner_text.strip,
  :link        => node.xpath( "./productUrl" ).inner_text.strip,

  :category    => Category.find_or_create_by_name( clean_field_key( node.xpath( "./CategoryName" ).inner_text ).downcase ),

  :price       => "£" + node.xpath( "./price" ).inner_text.strip
)

но это только я.Мне нравится иметь больше пробелов, особенно когда есть вложенные методы, и мне нравится иметь некоторое вертикальное выравнивание среди общих / похожих функций.Я считаю, что это облегчает сканирование кода и позволяет увидеть любые различия, что помогает, когда вы отлаживаете или ищете конкретную вещь.Опять же, это только мои предпочтения, но это то, чему я научился за многие годы написания кода на многих языках.

3 голосов
/ 19 февраля 2011

У меня есть похожие функции в некоторых моих приложениях. Я обычно помещаю эту логику в класс, например Importer. Таким образом, я могу использовать его из консоли и выполнить действие контроллера с контролем доступа, чтобы позволить другим использовать его из Интернета. Место, куда вы помещаете класс, не очень важно, если оно находится в пути загрузки приложения. Я склонен помещать мои в app / models против / lib только для того, чтобы при внесении изменений мне не приходилось перезагружать приложение в разработке.

...