2012-07-17 21 views
3

我在寻找什么必须是一个常见的情形最佳实践:按摩稀疏记录从一个Rails(ActiveRecord的,SQL)数据库表拉到友好为HTML渲染表的结构。将Rails的ActiveRecord中的稀疏数据转换为HTML表格的格式?

出于性能方面的原因,我做它返回的数据是这样的(我已经简化为清晰起见,例子)一个查询:

Lineitem.all 
=> [#<Lineitem id: 1, username: "Bob", category: "A", amount: 10>, 
    #<Lineitem id: 2, username: "Bob", category: "C", amount: 20>, 
    #<Lineitem id: 3, username: "Jen", category: "A", amount: 30>, 
    #<Lineitem id: 4, username: "Ken", category: "B", amount: 40>, 
    #<Lineitem id: 5, username: "Ken", category: "E", amount: 50>] 

我的目标是一个HTML表格是这样的:

   A  B  C  D  E 
      --- --- --- --- --- 
    Bob  10   20 
    Jen  30 
    Ken    40    50 
    Sam 

在每个类别被存储在一个数据库中的单独的列这将是微不足道的(或者,如果我使用NoSQL的......?!),或者如果我不关心分贝的性能。

为了解决它,我一直在写臭助手代码是这样的:在这个

# create hash lookup, index first by username then by category, eg: 
# ["Bob"]["A"] = #<Lineitem id: 1, ...> 
# ["Bob"]["C"] = #<Lineitem id: 2, ...> 
# ["Jen"]["A"] = #<Lineitem id: 3, ...> ... 
def index_lineitems(lineitems) 
    h = {} 
    lineitems.each do |li| 
    h[li.username] = {} unless h.key? li.username 
    h[li.username][li.category] = li 
    end 
    h 
end 

# look up value from indexed hash 
def get_lineitem_amount(indexed_lineitems, username, category) 
    if indexed_lineitems.key?(username) && indexed_lineitems[username].key?(category) 
    indexed_lineitems[username][category].amount 
    else 
    "" 
    end 
end 

或一些变化。然后我确定是什么行和列的最终名单将是(注意这个“山姆”行......),并通过循环,每次调用get_lineitem_amount渲染HTML表格。这是很糟糕的代码,我很尴尬地分享它。

当然还有一个更清洁,更面向对象和Rails友好的方式来这个共同的问题。

有什么建议吗?

回答

1

我做的非常相似稍微干净的东西:

比方说,这是在控制器:

@data = LineItem.all 

这是视图

columns = @data.map(&:category).uniq 

%table 
    %thead 
    %tr 
     %th &nbsp; 
     - columns.each do |column| 
     %th= column 
    %tbody 
    - @data.group_by(&:username).each do |username, rows| 
     %tr 
     %td= username 
     - cursor = 0 
     - rows.group_by(&:category).sort_by{|cat,rows| columns.index(cat)}.each do |category, rows| 
      - until cursor == columns.index(category) do 
      - cursor += 1 
      %td &nbsp; 
      %td= rows.sum(&:amount) 

它得到一吨清洁如果您将列存储在单独的数据库表中,并且只将它们包含到当前模型中,那么您可以将索引位置存储在对象上,而不需要在运行时计算它们,并且对订单没有很好的控制。一个额外的查询并不会打破应用程序的性能。

+0

感谢,这是有益的!我还计划探索使用一个中间对象,一个封装该逻辑清理视图更多(可能提供一个迭代?)我会后一个后续如果这个平移出来的。干杯。 – 2012-07-20 21:03:52

相关问题