RailsでN+1問題

  • N+1問題

一覧系画面を表示させる際、「全レコード取得 + 各レコードのデータ取得」分だけselect文を実行してしまう。的な問題。
例えばshopとmenuが1対Nの関係のDB構造のとき、以下のコードだと発生する
・sample_controller.rb

class SampleController < ApplicationController
  def index
    @menus = Menu.all
  end
end

・sample.html.erb

<% menus.each do |menu| %>
  <p><%= menu.name %></p>
  <p><%= menu.shop.name %></p>  <--ここでN回selectしてしまう
<% end %>
  • 解決策

最初にshop情報も一緒に取ってくる
・sample_controller.rb

class SampleController < ApplicationController
  def index
    @menus = Menu.includes(:shop).all
  end
end

メモ

RailsでBootstrap sassを使う方法
1. Gemfileに以下を追加

gem 'sass-rails', '~> 5.0'
gem 'coffee-rails', '~> 4.1.0'
gem 'bootstrap-sass', '~> 3.3.5'

2. /app/assets/stylesheets/application.cssを「application.css.scss」にリネームし以下を追加

@import "bootstrap";

3. /app/assets/javascripts/application.jsに以下を追加

//= require bootstrap

4. このままだとスマホでレスポンシブルにならないのでapplication.html.erb内に以下を追加

<meta name="viewport" content="width=device-width, initial-scale=1">



◇link_toにBootstrapのbtnクラスを適用する

<%= link_to 'ボタン', test_index_path, class: 'btn btn-warning btn-block' %>


メソッド

  • スタイル設定・取得
    • css : CSS取得
    • addClass, removeClass : クラスの設定・削除
// pタグの文字を赤字にする
$('p').css('color','red');
// pタグのcssのcolorを取得する
console.log($('p').css('color'));
// pタグにmyStyleクラスを追加する
$('p').addClass('myStyle');
  • html属性やカスタム属性を操作・取得
    • attr, data
// aタグのhref属性を取得
console.log($('a').attr('href'));
// aタグのhref属性を設定
$('a').attr('href', 'http://google.co.jp');
// aタグのカスタム属性(data-sitename)を取得
console.log($('a').data('sitename'));
  • タグの中身操作・取得
    • text, html
    • val
    • remove(要素削除), empty
// pタグの値を設定
$('p').text('just changed');
// pタグのhtml要素を設定
$('p').html('<a href="">click me !</a>');
// inputタグの値を取得
console.log($('input').val());
// pタグの全ての子要素を削除し空にする
$("p").empty();
  • 要素を追加する
    • before, after
    • insertBefore, insertAfter
    • prepend, append
    • prependTo, appendTo
// ul直下でindexが1のli要素の前に、'just added'のli要素を追加する
var li = $('<li>').text('just added');
$('ul > li:eq(1)').before(li);
// 別の書き方
li.insertBefore($('ul > li:eq(1)'));

// すべてのul要素の前にliを追加する
$('ul').prepend(li);
li.prependTo($('ul'));
  • エフェクト
    • hide, show
    • fadeOut, fadeIn
    • toggle
// idがboxの要素を隠す
$('#box').hide(800);
// idがboxの要素をフェードイン
$('#box').fadeIn(800);
// idがboxの要素をtoggle(あったら消す、なかったら出す)
$('#box').toggle(800);
// idがboxの要素をフェードアウトし、アラート出す
$('#box').fadeOut(800, function(){
  alert("done!");
});
  • イベント
    • click
    • mouseover, mouseout, mousemove
// idがboxの要素をクリックした際alertを表示する
$('#box').click(function(){
  alert('click!!!');
});
// idがboxの要素に、、、
$('#box')
  // マウスオーバーしたら背景色を緑にする
  .mouseover(function(){
    $(this).css('background','green');
  })
  // マウス離したら背景色を赤にする
  .mouseout(function(){
    $(this).css('background','red');
  })
  // マウス動かしたらマウスのx座標を表示する
  .mousemove(function(e){
    $(this).text(e.pageX);
  });
  • formで使える
    • focus, blur
    • change
// idがnameのフォーム、、、
$('name')
  // フォーカスした場合、背景色を赤にする
  .focus(function(){
    $(this).css('background','red');
  })
  // フォーカスを外した場合、背景色を白にする
  .blur(function(){
    $(this).css('background','white');
  });

// idがmembersの値が変わった場合アラートをあげる
$('#members').change(function(){
  alert('changed!!!');
});
  • 動的に作られた要素の指定
    • on
// buttonをクリックしたらvanishクラスを持つpタグを作成し、それをクリックしたら削除する
$('button').click(function(){
  var p = $('<p>').text('vanish!').addClass('vanish');
  $(this).before(p);
});
$('body').on('click', '.vanish', function(){
  $(this).remove();
});

セレクタ

基本は$('要素')

  • html要素(p h1 ul ...) ⇨ そのまま
【html部】
<p>jQueryの練習</p>

【jQuery部】
// p要素を赤文字にする
$('p').css('color','red');
  • id ⇨ #'id名'
【html部】
<p id="main">jQueryの練習</p>

【jQuery部】
// idがmainの要素を赤文字にする
$('#main').css('color','red');
  • class ⇨ .'class名'
【html部】
<p class="title">jQueryの練習</p>

【jQuery部】
// classがtitleの要素を赤文字にする
$('.title').css('color','red');
  • その他要素の指定
    • > ⇨ 直下の子要素
    • (空白) ⇨ それ以下の要素
    • , ⇨ 複数の要素
    • + ⇨ 隣接する要素
// main直下のitemクラスを赤字にする
$('#main>.item').css('color','red');
// main以下の全itemクラスを赤字にする
$('#main .item').css('color','red');
// p要素とitemクラスを赤字にする
$('p, .item').css('color','red');
// itemクラスに隣接するitemクラスを赤字にする
$('.item + .item').css('color','red');
  • フィルタを利用した要素指定
    • :eq(index), :gt(index), :lt(index) *1
    • :even, :odd
    • :contains(value)
    • :first, :last
// sub直下で2番目のli要素を赤字にする
$('#sub>li:eq(2)').css('color','red');
// sub直下で2番目以降のli要素を赤字にする
$('#sub>li:gt(1)').css('color','red');
// sub直下で偶数番目のli要素を赤字にする
$('#sub>li:even').css('color','red');
// sub直下のli要素で値に2を含むものを赤字にする
$('#sub>li:contains(2)').css('color','red');
// sub直下の最初のli要素を赤字にする
$('#sub>li:first').css('color','red');
  • メソッドを利用した要素指定
    • parent(), children()
    • next(), prev()
    • siblings()
// subとsubの親要素を赤字にする
$('#sub').parent().css('color','red');
// sub直下で2番目の次のli要素を赤字にする
$('#sub > li:eq(2)').next().css('color','red');
// sub直下で2番目のli要素の兄弟要素を赤字にする
$('#sub > li:eq(2)').siblings().css('color','red');
  • 属性セレクタ
    • =, !=, *=(〜を含む), ^=(〜で始まる), $=(〜で終わる)
// hrefが"http://google.com"の背景色を赤字にする
$('a[href="http://google.com"]').css('background','red');
// hrefが"http://google.com"以外の背景色を赤字にする
$('a[href="http://google.com"]').css('background','red');

*1:要素のindexは0から