繁体   English   中英

如何使这个Ruby on Rails页面更有效?

[英]How can I make this Ruby on Rails page more efficient?

我正在建立一个网站,用户可以在其中跟踪他们的龙与地下城的数据集(www.ddmdb.com)。 这个功能所涉及的模型/关系如下:

用户:

  • ID
  • 登录(用户名)
  • 一堆其他领域

微型:

  • ID
  • 名称
  • 数字(集合中的#,不计算)
  • release_id(外键)
  • 一堆其他字段和外键

所有权:

  • id(这真的需要吗?)
  • 用户身份
  • miniature_id
  • have_count
  • 最喜欢的(布尔)

我建立的相关关系如下:

用户:

  • has_many:所有权
  • has_many:minatures,:through =>:ownerships,:uniq => true,:conditions =>“ownerships.have_count> 0”
  • has_many:favorites,:through =>:ownerships,:source =>:miniature,:uniq => true,:conditions =>“ownerships.favorite = true”

袖珍:

  • has_many:所有权
  • has_many:owner,:through =>:ownerships,:source =>:user,:uniq => true,:conditions =>“ownerships.have_count> 0”

所有权:

  • belongs_to:用户
  • belongs_to:微型

我有一个页面,用户可以查看和更新​​他们的集合,以及查看其他用户的集合。 它包含网站上所有微缩模型的列表,以及每个微缩模型旁边的文本框,用户可以在其中输入每个缩略图的数量。 此功能也存在于微缩模型的子列表中(按类型,版本,大小,稀有度等进行过滤)

当用户创建帐户时,他们在所有权中没有条目。 当他们使用微缩模型的集合页面或子列表来更新其集合时,我在所有权表中仅为提交页面上的微缩模型创建条目。 因此,如果它是完整的Collection列表,我更新所有minis(即使计数为0)或者如果它是子列表,我只更新这些微缩模型。 因此,在任何时候,我可能拥有一个特定用户: - 所有权中没有条目 - 某些微缩模型的条目 - 所有微缩模型的条目。

我遇到的问题是我不知道如何使用“Rails方法”使用LEFT JOIN查询数据库,这样如果用户在所有权中没有微缩的条目,则默认为has_count 0.目前,我循环查看所有微缩模型时,我单独查询每个user_id / miniature_id组合,这显然效率很低。

视图:

<% for miniature in @miniatures %>
  <td><%= link_to miniature.name, miniature %></td>
  <td><%= text_field_tag "counts[#{miniature.id}]", get_user_miniature_count(current_user, miniature), :size => 2 %></td>
<% end %>

帮手:

def get_user_miniature_count(user, miniature)
  ownerships = user.ownerships
  ownership = user.ownerships.find_by_miniature_id(miniature.id)
  if ownership.nil?
    return 0
  else
    return ownership.have_count
  end
end

另一种解决方案是在用户注册时为所有微缩模型创建条目,但是当他们注册后向数据库添加新微缩时,我还必须为所有用户添加0 have_count。 这似乎有点复杂,但也许这是正确的方法?

有没有办法进行连接并为微缩模型提供默认值,其中该特定用户的所有权表中没有条目?

我要说的第一件事是用户模型应该拥有代码,该代码可以计算用户拥有的给定微缩数量,因为它看起来像“业务逻辑”而不是视图格式。

我的建议是在User模型中添加一个方法:

def owns(miniature_id)
  o = ownerships.detect { |o| o.miniature_id == miniature_id }
  (o && o.have_count) || 0
end

干编码,ymmv。

编辑:请注意,Rails一旦加载就会对所有权进行缓存,并且ActiveRecord不会像find那样覆盖检测,因此就像您期望它在数组上一样(即没有数据库操作)。

使用http://www.ruby-forum.com/topic/52385上的 fd建议和信息,我创建了以下方法:

def miniature_count(miniature_id)
  if @counts.nil?
    @counts = Hash.new
    ownerships.collect{|o| @counts[o.miniature_id] = o.have_count }
  end
  count = @counts[miniature_id] || 0
end

这最终比检测方法更快。

我挑了miniature_count拥有的名称,因为拥有这样应该返回一个布尔值,而不是一个整数的方法声音。

查询每个条目

完成2.61783(0 reqs / sec)| 渲染:1.14116(43%)| DB:1.34131(51%)| 200 OK [ http:// ddmdb / collection / 1]

检测方法

完成于2.20406(0 reqs / sec)| 渲染:1.87113(84%)| DB:0.21206(9%)| 200 OK [ http:// ddmdb / collection / 1]

哈希方法

完成0.41957(2 reqs / sec)| 渲染:0.19290(45%)| DB:0.10735(25%)| 200 OK [ http:// ddmdb / collection / 1]

我肯定需要添加缓存,但这肯定是一种改进。 我还怀疑我过早地优化了这段代码,但它是一个小网站,2.5秒的加载时间并没有让我开心。

也许我错过了一些东西,但你指定关系的方式似乎足以让rails自己弄清楚计数? 你试过吗?

编辑:在评论中重新讨论......怎么样:

<% ownerships=current_user.ownerships %> 
<% for miniature in @miniatures %>
  <td><%= link_to miniature.name, miniature %></td>
  <td><%= text_field_tag "counts[#{miniature.id}]", get_miniature_count(ownerships, miniature), :size => 2 %></td>
<% end %>

get_miniature_count()只是迭代所提供的所有权并返回0或计数如果微型出现在列表中? 我认为这将避免在'for'的每次迭代中再次返回DB。

编辑2:我还建议启动脚本/控制台并尝试直接在ruby中执行您想要的操作,即根据ruby而不是SQL测试所有权列表中的微缩模型成员资格。 通常,rails和activerecord足够聪明,可以在幕后为你做必要的SQL黑魔法,因为它知道关系。 如果您找到一个用户,然后执行user.methods,您将看到可用的内容。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM