为什么我的rails嵌套简单表单渲染速度如此之慢?

时间:2018-03-14 04:23:24

标签: ruby-on-rails ruby-on-rails-4 simple-form cocoon-gem

将Rails 4.2与以下相关宝石一起使用: 'jQuery的turbolinks' 'turbolinks','〜> 2.4.0' 'simple_form','〜> 3.0.2' “select2-rails”,“3.5.9.1” 'cocoon','〜> 1.2.6'

这是我在本地运行的控制台中有问题的页面/表单(注意View的问题很慢):

Started GET "/cases/2936/edit_case_contacts" for ::1 at 2018-03-06 18:39:13 -0800
Processing by CasesController#edit_case_contacts as HTML
  Parameters: {"id"=>"2936"}
  User Load (1.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1  ORDER BY "users"."id" ASC LIMIT 1  [["id", 90]]
  Case Load (1.2ms)  SELECT  "cases".* FROM "cases" WHERE "cases"."id" = $1 LIMIT 1  [["id", 2936]]
  Firm Load (1.0ms)  SELECT  "firms".* FROM "firms" WHERE "firms"."id" = $1 LIMIT 1  [["id", 16]]
  Contact Load (1.4ms)  SELECT "contacts"."first_name", "contacts"."last_name", "contacts"."email", "contacts"."company_name", "contacts"."id", "contacts"."type", "contacts"."prefix", "contacts"."suffix" FROM "contacts" WHERE "contacts"."firm_id" = $1  [["firm_id", 16]]
  Incident Load (1.3ms)  SELECT  "incidents".* FROM "incidents" WHERE "incidents"."case_id" = $1 LIMIT 1  [["case_id", 2936]]
  Medical Load (1.3ms)  SELECT  "medicals".* FROM "medicals" WHERE "medicals"."case_id" = $1 LIMIT 1  [["case_id", 2936]]
  Resolution Load (1.4ms)  SELECT  "resolutions".* FROM "resolutions" WHERE "resolutions"."case_id" = $1 LIMIT 1  [["case_id", 2936]]
  Rendered shared/_javascript_case_tabs.html.erb (0.6ms)
  Rendered shared/_case_tabs.html.erb (24.1ms)
  Rendered cases/_case_contact_fields.html.erb (5.0ms)
  CaseContact Load (1.3ms)  SELECT "case_contacts".* FROM "case_contacts" WHERE "case_contacts"."case_id" = $1  [["case_id", 2936]]
  Contact Load (1.9ms)  SELECT "contacts".* FROM "contacts" WHERE "contacts"."id" IN (2132, 2130, 1922, 1918, 1935, 1931, 1921, 2066, 2129, 2158, 2118)
  Rendered cases/_case_contact_fields.html.erb (6.0ms)
  Rendered cases/_case_contact_fields.html.erb (4.9ms)
  Rendered cases/_case_contact_fields.html.erb (4.9ms)
  Rendered cases/_case_contact_fields.html.erb (6.0ms)
  Rendered cases/_case_contact_fields.html.erb (5.3ms)
  Rendered cases/_case_contact_fields.html.erb (5.2ms)
  Rendered cases/_case_contact_fields.html.erb (5.4ms)
  Rendered cases/_case_contact_fields.html.erb (5.0ms)
  Rendered cases/_case_contact_fields.html.erb (5.4ms)
  Rendered cases/_case_contact_fields.html.erb (5.5ms)
  Rendered cases/_case_contact_fields.html.erb (5.3ms)
  Rendered cases/_case_contact_fields.html.erb (5.1ms)
  Rendered cases/_case_contact_fields.html.erb (6.1ms)
  Rendered cases/_case_contact_fields.html.erb (4.9ms)
  Rendered cases/_case_contact_fields.html.erb (4.8ms)
  **Rendered cases/edit_case_contacts.html.erb within layouts/application (197.9ms)**
  **Rendered layouts/_head.html.erb (311.1ms)**
  Rendered layouts/_navigation_links.html.erb (0.7ms)
  Rendered layouts/_navigation.html.erb (5.4ms)
   (1.7ms)  SELECT COUNT(*) FROM "notifications" WHERE (user_id = 90 and is_read = 'f')
  Case Load (2.5ms)  SELECT "cases".* FROM "cases" WHERE "cases"."firm_id" = $1  [["firm_id", 16]]
  Rendered time_entries/_form.html.erb (30.6ms)
  Rendered layouts/_side_navigation_javascript.html.erb (36.9ms)
  Rendered layouts/_side_navigation.html.erb (49.9ms)
  Rendered layouts/_messages.html.erb (0.5ms)
  Rendered layouts/_javascript_application.html.erb (0.5ms)
Completed 200 OK in 618ms (Views: 586.0ms | ActiveRecord: 16.0ms)
source=rack-timeout id=b6ee1bed757a24fb10c794c3e80d80ed timeout=15000ms service=646ms state=completed
source=rack-timeout id=f0cc00f68250d81864e108b8690fa9d4 timeout=15000ms state=ready
source=rack-timeout id=f0cc00f68250d81864e108b8690fa9d4 timeout=15000ms service=0ms state=active

这是我的形式,使茧部分:

<%= simple_form_for @case do |f| %>
  <div class="case-header">
    <div class="case-title">
      <div style="font-size: 24px;">
        <strong><%= @case.name %></strong><br>
      </div>
      <div id="case-buttons">
        <ul>
          <li><%= link_to 'Cancel', show_case_contacts_path(@case), :class => 'dark' %></li>
          <li><%= f.submit :class => 'sub2-small dark-right', :value => 'Save' %></li>
        </ul>
      </div>
    </div>
    <strong>Case #: </strong><%= @case.case_number %>

    <div class="container-fluid" style="padding: 0;">
      <div class="row">
        <div class="col-md-12">
          <%= render 'shared/case_tabs' %>
        </div>
      </div>
    </div>
  </div>

  <div class="case_contacts-edit-container">
    <%= link_to_add_association 'ADD CONTACT', f, :case_contacts, :"data-association-insertion-node" => "#header_row", :"data-association-insertion-method" => "after", class: 'action-button insure pull-right' %>
     <table id="info-table3">
      <tbody id="case_contacts_">
      <tr id="header_row">
        <td class="gray-back">
          <strong>Name</strong>
        </td>
        <td class="gray-back">
          <strong>Case Role</strong>
        </td>
        <td class="gray-back" colspan="2">
          <strong>Note</strong>
        </td>
      </tr>
        <%= f.simple_fields_for :case_contacts, f.object.case_contacts.includes(:contact).sort_by { |a| [a.name_of_contact_for_sorting] } do |case_contact| %>
          <%= render 'case_contact_fields', :f => case_contact, cache: true %>
        <% end %>
      </tbody>
    </table>
  </div>
<% end %>

<script type="text/javascript">
  $(document).ready(function() {
      $('select').select2();
  });
</script>

以下是部分内容:

<tr class="nested-fields insurance-field">
    <td>
        <%= f.association :contact, :collection => @firm_contacts, :prompt => "Add Contact", :class => 'table-input', :label => false, hint: false, input_html: { id: 'contact_prompt'} %>
    </td>
    <td>
        <div id="popup_case"></div>
        <%= f.input :role, collection: Contact::ROLES, :prompt => "Choose Role", :class => 'table-input', :label => false, hint: false, input_html: { id: 'role_prompt'} %>
    </td>
    <td colspan="2">
        <%= f.text_field :note, :prompt => "Add Note", :class => 'table-input-75', :label => false, hint: false %>

        <%= f.hidden_field :firm_id, :value => @firm.id, hint: false %>

        <%= link_to_remove_association f, class: 'dark-small remove_case_contacts' do %><span id="remove" class="glyphicon glyphicon-remove pull-right" original-title="Remove Contact", hint: false ></span><% end %>
    </td>
</tr>

<script type="text/javascript">
$(document).ready(function() {

      $('#case_contacts_').on('cocoon:before-insert', function() {

      })
      .on('cocoon:after-insert', function(e, insertedItem) {
             $('#contact_prompt').select2();
             $('#role_prompt').select2();
      })
      .on("cocoon:before-remove", function() {

      })
      .on("cocoon:after-remove", function() {
        /* e.g. recalculate order of child items */
      });

});
</script>

请注意,从上面的控制台日志中可以看出_head部分速度非常慢,这里它是:

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= content_for?(:title) ? yield(:title) : "Litigo | Legal Software" %></title>
  <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "Litigo | Legal Software" %>">
  <link href="<%= Rails.env.production? ? 'https' : 'http' %>://fonts.googleapis.com/css?family=Arimo:400,700|Changa+One" rel='stylesheet' type='text/css'>
  <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= stylesheet_link_tag 'application', "#{Rails.env.production? ? 'https' : 'http'}://fonts.googleapis.com/css?family=Arimo:400,700|Changa+One" %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <script type="text/javascript" src="https://js.stripe.com/v2/"></script>
  <%= csrf_meta_tags %>
  <% tag :meta, :name => "stripe-key", :content => STRIPE_PUBLIC_KEY %>
  <%= favicon_link_tag 'favicon.png' %>
</head>

我不确定如何减少渲染时间。我甚至没有看到任何低悬的果实......帮助!

1 个答案:

答案 0 :(得分:1)

这是开发还是生产?因为如果它是开发,那就可以解释为什么_head较慢(因为没有预编译的资产)。

我注意到的事情:

    从数据库中取出后调用edit_case_contacts的{​​{1}}中的
  • (为什么不让数据库立即对数据进行排序?)
  • 在局部你有一段javascript似乎对所有部分都相同,所以提取它
  • 另外:最好将所有javascript洒在单独的js中,从那以后它可以在生产中预编译并包含在application.js中

[编辑:如何对“联系人姓名”进行排序]

您现在写下以下内容:

sort_by

这将获取包括联系人在内的案例联系人,返回错误,然后使用f.object.case_contacts.includes(:contact).sort_by { |a| [a.name_of_contact_for_sorting] } 对该数组进行排序。使用sort_by让数据库对此进行排序会更有效率。写点像

order

假设您有联系人的属性名称。更多选择:

  • f.object.case_contacts.includes(:contact).order("contacts.name") 对多个字段进行排序
  • .order("contacts.last_name, contacts.first_name").order("contacts.name asc")选择方向