Ruby on rails Rails重构视图中的块-我可以更高效地编写它吗?
我正在尝试为rails中的表设置逻辑。基本上,这是一个时间表应用程序,我想做的是设置它,如果你达到目标,它会显示绿色。如果你快到了,黄色的。如果你离得不近的话,红色的。我下面的代码可以工作。然而,看看我的日志,它似乎效率极低。我怎样才能写得更好 这里是风景。users/hours.html.erbRuby on rails Rails重构视图中的块-我可以更高效地编写它吗?,ruby-on-rails,refactoring,views,Ruby On Rails,Refactoring,Views,我正在尝试为rails中的表设置逻辑。基本上,这是一个时间表应用程序,我想做的是设置它,如果你达到目标,它会显示绿色。如果你快到了,黄色的。如果你离得不近的话,红色的。我下面的代码可以工作。然而,看看我的日志,它似乎效率极低。我怎样才能写得更好 这里是风景。users/hours.html.erb <div class="page-header"><h1>Weekly Timesheets</h1></div> <table cla
<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>
我想这应该管用 在
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
在您的视图中
<% @users.each do |user| %>
<tr class="<%= user.user_css %>">
...
</tr>
<% end %>
...
dax所说的是正确的,但请不要将该代码放在您的模型中。
您可以使用presenter模式或decorator模式。我发现
非常有用。
在本例中,您将创建一个用户装饰器,其中包含专门为此视图返回数据的所有方法。比如:
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
类UserDecorator=hours\u成功
“成功”
elsif object.add_hours>=小时警告
“警告”
其他的
“错误”
结束
结束
成功
object.has_角色?:工作人员10:15
结束
def小时警告
object.has_角色?:工作人员6:12
结束
结束
您可以添加此视图或其他视图所需的任何方法。阅读有关如何使用gem的draper文档。这是一个重构版本。我做了以下更改:
- 将状态逻辑拉入用户#进度#状态,并对其进行重构,以使其更可重用并清理视图
- 用于视图中的循环,因为它更具可读性
- 重命名用户#将#小时数添加到总#小时数中,因此它不意味着添加(命令),而只是一个虚拟属性(这是一个查询)
- 删除了方法中的订单范围,因为在这种情况下不需要订单范围
- 使total_hours将其结果缓存在用户上,因此多个后续调用不会多次命中数据库(正如我们在progress status中所做的那样)
<% 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 %>
您可以进一步使用最后一种方法(当提供更多上下文时),但现在应该可以了。我认为这种情况不适合这些模式。这段代码的大部分都带有域逻辑的味道(除了#role_name),因此理想情况下应该将其放入域模型中。这使得它比decorator/presenter模式更易于重用。首先,我们可以将其放入AR模型中(它在一开始就完成了这项工作),然后我们可以将其提取到域类中(并避免fat模型反模式)。目前,另一个解决方案奏效了。谢谢你让我知道德雷珀的事!好吧,在域模型中可能会有小时数,我真的不知道这些小时数是什么意思,但是css类不能进入模型中。。。这是纯粹的表示逻辑,也是角色名的具体化。如果你将小时数配置移动到角色模型中,你的演示者会更干净。好的,这就是我最后选择的。下面所有的答案都很好。但有一件事我必须改变。对于视图,我必须将
更改为
,并且效果良好。这个解决方案工作得很好,减少了负载。非常感谢你!作为rails程序员的初学者,我感谢您!你说得对,这是一个打字错误,我现在改正了,以备将来参考。很高兴它能帮上忙=)这个也能用,不过我喜欢jurglic用来计算小时数的逻辑。谢谢你这么快回复!
<% 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