簡體   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