【问题标题】:Nokogiri XML import feed organisation?Nokogiri XML import feed organisation?
【发布时间】:2011-06-30 08:51:00
【问题描述】:

我建立了一个网站,该网站依赖于我目前使用 Nokogiri 解析的 XML 提要。尽管我的管理控制器中当前拥有所有代码,但一切正常且花花公子,因此我实际上可以通过 URL 调用导入,即/admin/import/

我不禁认为这不属于控制器。有没有更好的方法来做到这一点,即将代码移动到独立的import.rb 文件中,以便只能从控制台访问?如果是这样,我需要把这个文件放在哪里,在/lib/ 目录中?

这是一个代码sn-p:

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

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 nokogiri


    【解决方案1】:

    您的代码听起来可以作为 Rails 运行程序脚本运行。它们是在您网站的正常 Rails 进程之外运行的脚本,但可以完全访问 ActiveRecord 设置,因此您可以轻松访问您的数据库。

    我认为 Rails 对文件位置的要求不像对所有其他文件那样严格,但我会在 'app' 下创建一个名为 'scripts' 的子目录并将其放在那里。保持一个整洁的目录结构对维护是一件好事。

    你没有说你是在运行 Rails 3 还是以前的版本。如果您正在运行 Rails 3,请在 Rails 应用程序的命令行中键入 rails runner -h 以获取更多信息。

    有些人认为脚本应该使用 rake 运行,我同意 IF 他们正在操作文件和文件夹并对运行您的应用程序的 Rails 空间进行一般维护。如果您重新执行作为数据库内务管理一部分的定期任务,或者在您的情况下,检索用于支持您的应用程序的内容,我认为它应该是一个“跑步者”任务。

    您可以构建功能,以便仍然可以通过 URL 触发代码运行,但我认为这可能会被滥用,尤其是当您可以覆盖所需数据或用重复/冗余数据填充数据库时。我认为最好通过操作系统启动的 cron 定期运行任务,只是为了让事情保持良好的间隔,或者只手动运行。如果您通过 URL 访问保持它可用,我建议您使用密码来帮助避免滥用。

    最后,作为长期从事此工作的人,我建议在您的代码中使用一些结构和对齐方式:

    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
    )
    

    但这只是我。我喜欢有更多的空白,尤其是当有嵌套方法时,我喜欢在常用/相似函数之间进行一些垂直对齐。我发现它可以更轻松地扫描代码并查看任何差异,这在您调试或寻找特定事物时会有所帮助。同样,这只是我的偏好,但这是我多年来用多种不同语言编写代码所学到的东西。

    【讨论】:

      【解决方案2】:

      我的一些应用中有类似的功能。我通常把这个逻辑放在一个类中,例如Importer。这样我既可以从控制台使用它,又可以进行访问控制的控制器操作以让其他人从 Web 使用它。你把类放在哪里并不是很重要,只要它在应用程序的加载路径中。我倾向于将我的放在 app/models 中而不是 /lib 中,这样我在进行更改时就不必重新加载开发中的应用程序。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-27
        • 2012-12-15
        • 1970-01-01
        • 1970-01-01
        • 2013-02-16
        • 2014-12-23
        相关资源
        最近更新 更多