我试图更好地保持逻辑不受我的观点和模型的影响。我正在构建一个Rails应用程序。它有Review
模型和Album
模型。这是album/show.html.erb
视图中的一些逻辑。我想将其移至Review
模型,但我不确定如何做到这一点。
<% @reviews.each do |r| %>
<div>
<div class="review-rating" data-number="<%= r.rating %>">
</div>
<p class="white"><%= r.comment %></p>
<p class="grey"><i>posted <%= time_ago_in_words(r.created_at) %> ago</i></p>
<% if user_signed_in? %>
<% if current_user.id == r.user_id %>
<%= link_to 'Edit', edit_album_review_path(@album, r.id), class: 'grey' %> |
<%= link_to 'Delete', album_review_path(@album, r.id), method: :delete, data: {confirm: "Are you sure?"}, class: 'grey' %>
<br /><br />
<% end %>
<% else %>
<br />
<% end %>
</div>
<% end %>
具体来说,我想移动这部分
<p class="grey"><i>posted <%= time_ago_in_words(r.created_at) %> ago</i></p>
我对代码依赖于.each
方法这一事实感到困惑。我不确定如何在模型中解决这个问题。我试过这个:
<p class="grey"><i><%= time_posted(r) %></i></p>
在review.rb
模型中
def time_posted(r)
"posted #{time_ago_in_words(r.created_at)} ago"
end
但是Rails抛出了这个错误:
“#&lt;#:0x007fff2ab8a8e0&gt;”的未定义方法`time_posted'“
帮助将不胜感激。
答案 0 :(得分:1)
在视图中保留 view 逻辑没有错。在您的情况下,您将按照您希望将其呈现给用户的方式迭代评论和格式化。考虑一下,如果你想改变你显示“发布”的方式,比如说,以前的数字,哪里是合理的地方去修改它?模型?不要这么认为,模型保持和操作数据,视图代表它,所以你的例子对我来说似乎很好。
答案 1 :(得分:1)
让我们暂时讨论一下,看看我们如何能够挽救你的尝试:
class Review
def time_posted
"posted #{ time_ago_in_words(self.created_at) } ago"
end
end
我们更改了方法,使其适用于self
- 意味着该方法所属的对象:
<p class="grey"><i><%= r.time_posted %></i></p>
然而它非常漂亮 - 我们从视图中移除了逻辑,但我们将其填入模型中。模型工作是跟踪业务逻辑,当你考虑实际推入轨道中的模型(验证,回调,I18n,关联,状态跟踪等)时,推送表示逻辑变得非常缺乏吸引力
那你能做什么?
module ReviewHelper
def time_posted(r)
"posted #{ time_ago_in_words(r.created_at) } ago"
end
end
<p class="grey"><i><%= time_posted(r) %></i></p>
基本上帮助程序只是模块 - rails使用/app/helpers
中声明的所有帮助程序并使用它们来扩展视图上下文,以便您可以从视图中调用它们。它简单,并保持视图逻辑隐藏。
class ReviewPresenter < SimpleDelegator
def time_posted(r)
"posted #{ time_ago_in_words(r.created_at) } ago"
end
end
class Review
def present
@presenter ||= ReviewPresenter.new(self)
end
end
<% @reviews.map(:present).each do |r| %>
<p class="grey"><i><%= r.time_posted %></i></p>
<% end %>
这使得它很好并且封装了,并避免将大量方法放入&#34;全局&#34;像帮助程序一样查看上下文命名空间。但是,如果它值得额外的复杂性取决于你。
有几种宝石可以使演示者模式更容易使用draper。