Ruby on rails 在rails中高效地获取父对象
我正在写一个图像库。Ruby on rails 在rails中高效地获取父对象,ruby-on-rails,ruby-on-rails-3,Ruby On Rails,Ruby On Rails 3,我正在写一个图像库。 库中的图像属于项目。每个项目都可以有一个父项目。 例如project1>project2>project3>image1 为了允许管理员使用FTP,我希望文件有“漂亮”的路径。 缩略图和预览存储在ROOT/previews/和ROOT/Thumbnails/中,而图像存储在ROOT/images///…/ 管理员可以简单地将图像上传到正确的文件夹,应用程序将发现它们并处理所有事情 这当然会导致在获取图像路径时必须获取所有父对象的问题。目前,这意味着首先获取图像,然后是项目,
库中的图像属于项目。每个项目都可以有一个父项目。
例如
project1>project2>project3>image1
为了允许管理员使用FTP,我希望文件有“漂亮”的路径。缩略图和预览存储在
ROOT/previews/
和ROOT/Thumbnails/
中,而图像存储在ROOT/images///…/
管理员可以简单地将图像上传到正确的文件夹,应用程序将发现它们并处理所有事情 这当然会导致在获取图像路径时必须获取所有父对象的问题。目前,这意味着首先获取图像,然后是项目,然后是父项目,依此类推。
如果总是一个祖先(嵌套级别),那么问题很容易解决,问题出在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
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
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
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
请求示例如下所示:
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
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
可以使用嵌套集模型来存储项目。使用它,您可以简单地获取项目,然后在一个查询中获取项目的所有父项 维基百科关于嵌套集:
用于嵌套集的Rails插件:
发布了
schema.rb
,是否也要实现?这是一个相当空的ATM机(大部分都有:属于)如果你有多个或有一个关联,那也不错。我不太明白的是,你怎么能有“0个或更多”父母有属于关联。你是说0还是1?我是说,0个或更多的祖先,但是的,它只是0或1个父母。但该父级可以有0个或1个父级,以此类推。啊,好吧,0个或更多与嵌套级别有关。我看到插入非常慢,不是我期望有很多插入,但仍然如此。是的,这是缺点。不过,“非常慢”是相对的,除非你期望有很多很多项目,否则我怀疑这会是一个问题。好吧,我希望它是可伸缩的(当然不是facebook的大小,但仍然),多少是“很多”?我不确定;几千?您可以相当快地进行设置,为自己播种大量项目,并运行一些基准测试,以查看性能何时开始真正下降。我认为插入可能需要很长时间,因为您需要在每次插入/删除时更新整个表