我正在写一个图片库
图库中的图像属于项目。每个项目都可以有一个父项目
一个例子是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
答案 0 :(得分:1)
您可以使用嵌套集模型来存储项目。使用它,您只需获取项目,然后在一个查询中获取项目的所有父项。
关于嵌套集的维基百科:
http://en.wikipedia.org/wiki/Nested_set_model
嵌套集的Rails插件:
https://github.com/collectiveidea/awesome_nested_set