1

Rails でテーブルのロジックをセットアップしようとしています。基本的にはタイムシート アプリケーションであり、私がやりたいことは、目標を達成した場合に緑色で表示されるように設定することです。あなたがほとんどそこにいる場合は黄色。近くにいない場合は赤になります。以下のコードは機能します。しかし、私のログを見ると、ひどく非効率的です。どうすればこれをよりうまく書くことができますか?

これがビューです。users/hours.html.erb

    <div class="page-header"><h1>Weekly Timesheets</h1></div>

<table class="nicetable table-condensed">
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
      <th>Total Hours</th>
      <th>Role</th>
      <th>Change Role</th>
      <th>Timesheet</th>
    </tr>
  </thead>
  <tbody>
  <% @users.each do |user| %>
    <tr class="<%= 'success' if user.has_role? :staff and user.add_hours >= 10 %><%= 'warning' if user.has_role? :staff and user.add_hours < 10 and user.add_hours > 6 %><%= 'error' if user.has_role? :staff and user.add_hours >= 0 and user.add_hours <= 6 %><%= 'success' if user.has_role? :new_staff and user.add_hours >= 15 %><%= 'warning' if user.has_role? :new_staff and user.add_hours < 15 and user.add_hours >= 12 %><%= 'error' if user.has_role? :new_staff and user.add_hours < 12 and user.add_hours >= 0 %>">
      <td><%= user.name%></td>
      <td><%= user.email %></td>
      <td><%= user.add_hours %></td>
      <td><%= user.roles.first.name.titleize unless user.roles.first.nil? %></td>
      <td>
        <a data-toggle="modal" href="#role-options-<%= user.id %>" class="btn btn-mini" type="button">Change role</a>
        <%= render user %>
      </td>
      <td><%= link_to 'Timesheet', user_timesheets_path(user, @timesheets), class: "btn btn-mini" %>
    </tr>

そして、これが私のユーザーモデルです。

    def add_hours
  self.timesheets.where('day BETWEEN ? AND ?', Date.today.beginning_of_week, Date.today.end_of_week).order('created_at DESC').sum{|p| p.teacher + p.conversation + p.study}

 end
4

3 に答える 3

1

ダックスが言ったことは正しいですが、モデルにそのコードを入れないでください。プレゼンター パターンまたはデコレーター パターンを使用できます。draper gemは 非常に便利だと思います。あなたの場合、このビュー専用のデータを返すすべてのメソッドを使用してユーザー デコレータを作成します。何かのようなもの:

class UserDecorator < Draper::Decorator
  delegate_all

  def role_name
    object.roles.first.name.titleize if object.roles.first.present?
  end

  def hours_stauts
    if object.add_hours >= hours_success
      'success'
    elsif object.add_hours >= hours_warning
      'warning'
    else
      'error'
    end
  end

  def hours_success
    object.has_role? :staff ? 10 : 15
  end

  def hours_warning
    object.has_role? :staff ? 6 : 12
  end
end

このビューまたは他のビューに必要なメソッドを追加できます。gem の使用方法については、draper のドキュメントを参照してください。

于 2013-08-21T10:50:08.597 に答える
1

ここにリファクタリングされたバージョンがあります。次の変更を加えました。

  • ステータス ロジックを user#progress_status に取り出し、リファクタリングして再利用しやすくし、ビューをクリーンアップしました
  • より読みやすいため、ビューでループに使用されます
  • user#add_hours の名前を total_hours に変更したため、追加 (コマンド) ではなく、単なる仮想属性 (クエリ) を意味します。
  • この場合は必要ないため、メソッドの order スコープを削除しました
  • total_hours がその結果をユーザーにキャッシュするようにしたので、複数の後続の呼び出しが DB に複数回ヒットすることはありません (進行状況内で行うように)。

まずは景色。tbody 内のコンテンツのみを含めました。

<% for user in @users %>                                                         
    <tr class="<%= user.progress_status.to_s %>">                                  
      <td><%= user.name %></td>                                                    
      <td><%= user.email %></td>                                                   
      <td><%= user.total_hours %></td>                                               
      <td><%= user.roles.first and user.roles.first.name.titleize %></td>          
      <td>                                                                         
        <a data-toggle="modal" href="#role-options-<%= user.id %>" class="btn btn-mini" type="button">Change role</a>
        <%= render user %>                                                         
      </td>                                                                        
      <td><%= link_to 'Timesheet', user_timesheets_path(user, @timesheets), class: "btn btn-mini" %></td>
    </tr>                                                                          
  <% end %>

そして、リファクタリングされたユーザー モデル メソッド:

def total_hours                                                                    
  @total_hours ||= timesheets                                                   
    .where('day BETWEEN ? AND ?', Date.today.beginning_of_week, Date.today.end_of_week)
    .sum {|p| p.teacher + p.conversation + p.study}                             
end                                                                             

def progress_status                                                             
  if has_role? :staff                                                           
    if total_hours >= 10                                                           
      :success                                                                     
    elsif (7..9).include? total_hours                                           
      :warning                                                                     
    else                                                                           
      :error                                                                       
    end                                                                                                                                         
  elsif has_role? :new_staff                                                       
    if total_hours >= 15                                                           
      :success                                                                     
    elsif (12..14).include? total_hours                                            
      :warning                                                                     
    else                                                                           
      :error
    end
  end
end

最後の方法 (より多くのコンテキストが提供されている場合) をもう少し使用することもできますが、今のところは問題ありません。

于 2013-08-21T11:28:32.160 に答える
0

これはうまくいくはずだと思います!

user.rb

def user_css
  if self.has_role? :staff do |staff|
    if staff.add_hours >= 10
      'success'
    elsif staff.add_hours >= 6
      'warning'
    else
      'error'
  end
  if self.has_role? :new_staff do |new_staff|
    if new_staff.add_hours >= 15
      'success'
    elsif new_staff.add_hours >= 12
      'warning'
    else
      'error'
  end
end

あなたのview

<% @users.each do |user| %>
  <tr class="<%= user.user_css %>">
    ...
  </tr>
<% end %>
于 2013-08-21T09:30:58.990 に答える