清理膨胀的视图

时间:2014-10-01 13:53:32

标签: ruby-on-rails

我对rails很新,所以我的倾向是膨胀观点。 rack-mini-profiler显示我的加载时间的2/3和来自渲染我的视图的1/2我的sql调用。我正在寻找一些关于如何清理它的建议,以及一些用于更有效地编码应用程序的好资源。

我有使用旅行的用户(:city_id,:start_date,:end_date)这些旅程属于属于国家/地区的城市。

控制器

# this grabs topics that are concidered genral
@feed = Topic.where(:city_id => current_user.trips.pluck(:city_id), :general_topic => true).uniq
# topics that are specific to a users trip time range
current_user.trips.each do |trip|
    @feed += Topic.where("(general_topic = ? AND city_id = ?) AND ((start_date BETWEEN ? AND ? OR end_date BETWEEN ? AND ?) OR (start_date <= ? AND end_date >= ?))", false, trip.city_id, trip.start_date, trip.end_date, trip.start_date, trip.end_date, trip.start_date, trip.end_date).uniq
end

视图

<% @feed.each do |topic| %>
<% if topic.general_topic %>
    <div>
        <div>
            <h3>
                <%= link_to(topic) do %>    
                    <%= topic.title %>  
                <% end %>
            </h3>
        </div>
        <div>
        <p><%= time_ago_in_words(topic.created_at) %> by <%= link_to topic.user.name, "#" %> about <%= topic.city.name %>, <%= topic.city.country.name %></p>
        </div>
        <div>
            <p><%= topic.comments.size %> comments 
                <% if topic.comments.any? %>
                (<%= time_ago_in_words(topic.comments.last.updated_at) %> ago)
                <% end %></p>
        </div>      
    </div>      
<% else %>
    <div>
        <div>
            <h3>
                <%= link_to(topic) do %>    
                    <%= topic.title %>  
                <% end %>
            </h3>
        </div>
        <div>
        <p><%= time_ago_in_words(topic.created_at) %> by <%= link_to topic.user.name, "#" %> in <%= topic.city.name %>, <%= topic.city.country.name %> <%= topic.start_date.strftime("%m/%d") %>-<%= topic.end_date.strftime("%m/%d") %></p>
        </div>
        <div>
            <p><%= topic.comments.size %> comments 
                <% if topic.comments.any? %>
                (<%= time_ago_in_words(topic.comments.last.updated_at) %> ago)
                <% end %></p>
        </div>  
    </div>      
<% end %>       
<% end %>
</div> <!-- end discussions -->

我知道这非常可怕。但是我希望这个话题看起来像这样:

Topic.Title
topic.created_at "by" topic.user.name "about" topic.city.name "," topic.city.country.name
topic.comments.count (topic.comment.last.created_at)

为了在控制器或模型中获得一些逻辑,我应该开始研究什么? 目前我的Topic模型只是:

class Topic < ActiveRecord::Base
belongs_to :user
belongs_to :trip
belongs_to :city
has_many :comments, :class_name => 'Comment', :foreign_key => :topic_id
default_scope { order("created_at DESC")}

1 个答案:

答案 0 :(得分:0)

你可以做一些事情,速度和可读性。

为了提高速度,请使用includes在控制器中加载数据。例如,当您加载主题时,您也可以加载相关的注释:

@feed = Topic.where(:city_id => current_user.trips.pluck(:city_id), :general_topic => true).includes(:comments)

请参阅Rails 4: How to use includes() with where() to retrieve associated objects

通常,您应该最小化在视图中执行的数据库调用量:在控制器中完成后,它们都在一个地方完成,并且易于阅读和维护。

为了便于阅读,您可以干掉(“不要重复自己”)代码。查看if和else块的内容:它们几乎完全相同:如果主题不是.general_topic,则显示一条额外的行。为什么重复这么多相同的东西?你可以这样重写它:

<% @feed.each do |topic| %>
  <div>
    <div>
      <h3>
        <%= link_to(topic) do %>    
          <%= topic.title %>  
        <% end %>
      </h3>
    </div>
    <div>
      <p>
        <%= time_ago_in_words(topic.created_at) %> by <%= link_to topic.user.name, "#" %> about <%= topic.city.name %>, <%= topic.city.country.name %>
        <% unless topic.general_topic %>
          <%= topic.start_date.strftime("%m/%d") %>-<%= topic.end_date.strftime("%m/%d") %>
        <% end %>        
      </p>
    </div>
    <div>
      <p><%= topic.comments.size %> comments 
        <% if last = topic.comments.last %>
          (<%= time_ago_in_words(last.updated_at) %> ago)
        <% end %>
      </p>
    </div>      
  </div>  
<% end %>    

请注意,我删除了topic.comments.any?并将其替换为一些代码以获取最后一个,并测试它是否存在。这是语法糖(一旦发生了急切的加载),但在我看来读得更清楚。