简体   繁体   English

清理肿的视图

[英]Cleaning up bloated views

I am fairly new to rails, so my tendency is to bloat the views. 我对Rails很陌生,所以我的倾向是夸大意见。 rack-mini-profiler shows 2/3 of my load time and 1/2 my sql calls from rendering my views. rack-mini-profiler显示了我的视图的2/3的加载时间和1/2的sql调用。 I'm looking for some advice on how to clean this up, as well as some good resources for coding apps more efficiently. 我正在寻找有关如何清理此问题的建议,以及一些有效的应用程序编码资源。

I have Users with Trips(:city_id, :start_date, :end_date) these Trips belongs_to a City which belongs_to a Country. 我有使用Trips(:city_id,:start_date,:end_date)的用户,这些Trips属于一个城市,属于一个国家。

controller 控制者

# 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

view 视图

<% @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 -->

I know this is pretty horrific. 我知道这太可怕了。 But what I want the topic to look something like this: 但是我希望主题看起来像这样:

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)

What should I start looking into in order to get some logic into the controller or model? 为了使控制器或模型具有一些逻辑,我应该开始研究什么? currently my Topic model is just: 目前我的主题模型是:

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")}

There's a few things you can do, for speed and readability. 为了提高速度和可读性,您可以做一些事情。

For speed, eager-load your data in the controller, using includes . 为了提高速度,请使用includes将数据急于加载到控制器中。 Eg, when you load the topics you can load the associated comments too: 例如,当您加载主题时,您也可以加载相关的注释:

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

see Rails 4: How to use includes() with where() to retrieve associated objects 参见Rails 4:如何将include()与where()一起使用以检索关联的对象

Generally, you should minimise the amount of database-calling you do in your views: when it's done in the controller, it's all done in one place and is easy to read and maintain. 通常,应尽量减少在视图中执行的数据库调用量:在控制器中完成时,所有这些操作都在一个地方完成,并且易于阅读和维护。

For readability, you can DRY ("don't repeat yourself") up your code. 为了提高可读性,您可以将代码DRY(“不要重复自己”)。 Look at the contents of the if and else blocks: they are almost identical: you show an extra line if topic isn't .general_topic. 查看if和else块的内容:它们几乎相同:如果topic不是.general_topic,则显示多一行。 Why repeat so much identical stuff? 为什么要重复这么多相同的东西? You could rewrite it thus: 您可以这样重写它:

<% @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 %>    

Note that i removed topic.comments.any? 请注意,我删除了topic.comments.any? and replaced it with some code to get the last one, and test if it exists. 并用一些代码替换它以获得最后一个,并测试它是否存在。 This is syntactic sugar (once the eager loading is happening) but reads more clearly in my opinion. 这是语法糖(一旦发生了急切的加载),但我认为阅读起来会更清楚。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM