在铁轨中有效地抚养父母

时间:2011-09-03 16:36:56

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

我正在写一个图片库 图库中的图像属于项目。每个项目都可以有一个父项目 一个例子是project1 > project2 > project3 > image1

为了让管理员能够使用FTP,我想拥有文件的“漂亮”路径 缩略图和预览存储在ROOT/previews/<image-id>ROOT/thumbnails/<image-id>中,而图像存储在ROOT/images/<project-name>/<project-name>/.../<image-name>中 然后,管理员可以简单地将图像上传到正确的文件夹,应用程序将发现它们并处理所有内容。

这当然会导致在获取图像路径时必须获取所有父项的问题。目前这意味着首先获取图像,然后是项目,然后是项目父项,等等 如果它始终是一个祖先(嵌套级别),那么问题就很容易了,问题就是0或者更多。

我不希望项目嵌套得非常深,但我仍然担心每个请求有很多查询都不好。

有什么方法可以避免这种情况吗?也许一起取一个? 也许我应该一起跳过FTP上传,只允许从UI拖放?

也许我太担心了,我只是通过索引字段限制查询


我的schema.rb目前看起来像这样:

ActiveRecord::Schema.define(:version => 20110827230616) do

  create_table "images", :force => true do |t|
    t.string   "name"
    t.string   "filename"
    t.text     "info"
    t.integer  "project_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "images", ["project_id", "filename"], :name => "index_images_on_project_id_and_filename", :unique => true

  create_table "projects", :force => true do |t|
    t.string   "name"
    t.text     "info"
    t.string   "dates"
    t.integer  "parent_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "projects", ["parent_id", "name"], :name => "index_projects_on_parent_id_and_name", :unique => true

end

image.rb

class Image < ActiveRecord::Base
  belongs_to :project

  # Validation
  validates_presence_of :project_id, :filename

  attr_readonly :filename

  def path
    if not self.project_id or not self.project
      raise "Called path on an image without a project"
    end
    return File.join(self.project.path, self.filename)
  end

  def thumbnail_path
    raise "Called thumbnail_path on an image without an id" unless self.id
    return File.join(Rails.application.config.thumbnail_directory, self.id.to_s)
  end

  def preview_path
    raise "Called preview_path on an image without an id" unless self.id
    return File.join(Rails.application.config.preview_directory, self.id.to_s)
  end

  def exists?
    if not File.file? self.path
      return false
    end

    return true
  end
end

project.rb

class Project < ActiveRecord::Base
  belongs_to :parent, :class_name => 'Project'
  has_many   :children, :class_name => 'Project', 
             :dependent => :destroy, :foreign_key => 'parent_id'
  has_many   :images, :dependent => :destroy

  def safe_name
    return self.name.downcase.gsub(/\s/, '-').gsub(/[^a-z0-9-]/, '_')
  end

  def path
    tmp = self
    parents = []
    while tmp
      parents.insert(0, tmp.safe_name)
      tmp = tmp.parent
    end

    return File.join(Rails.application.config.image_directory, parents)
  end
end

示例请求可能如下所示:

Started GET "/images/1" for 127.0.0.1 at Sat Sep 03 10:23:30 -0700 2011
  Processing by ImagesController#show as HTML
  Parameters: {"id"=>"1"}
  Image Load (0.2ms)  SELECT "images".* FROM "images" WHERE "images"."id" = ? LIMIT 1  [["id", "1"]]
  Project Load (0.2ms)  SELECT "projects".* FROM "projects" WHERE "projects"."id" = 2 LIMIT 1
  Project Load (0.2ms)  SELECT "projects".* FROM "projects" WHERE "projects"."id" = 1 LIMIT 1
  Project Load (0.1ms)  SELECT "projects".* FROM "projects" WHERE "projects"."id" IS NULL LIMIT 1

1 个答案:

答案 0 :(得分:1)

您可以使用嵌套集模型来存储项目。使用它,您只需获取项目,然后在一个查询中获取项目的所有父项。

关于嵌套集的维基百科:
http://en.wikipedia.org/wiki/Nested_set_model

嵌套集的Rails插件:
https://github.com/collectiveidea/awesome_nested_set