狠狠撸

狠狠撸Share a Scribd company logo
ステップバイステップ
で解説!Rails検索処理
Ruby / Ruby on Rails ビギナーズ勉強会 第9回 #coedorb
photo by poluz!
http://www.?ickr.com/photos/poluz
自己紹介
? 派遣で6年程エンジニア&PM
? WindowsのActiveDirecotryとか
? 2005年~2014年までは人材系の仕事
? エンジニア専門のキャリアコンサルタント
? 昨年からなぜかフリーランス
? しかもWeb系のエンジニア
? Rails4+AngularJS。最近は仕事でRubyでク
ローラー開発とかも行う
? http://qiita.com/h5y1m141@github/
items
? 実はJavaScriptが好きでこっちのほうが経験が長
い
?Titanium Mobile、Node.js、最近だとNW.js
?(最近メンテ辞めましたが)クラフトビールが飲め
る買えるお店が探せるスマフォアプリ、Webサイト
を全部JavaScriptベースの技術で作ってました
?jeffrey james pacres
http://www.?ickr.com/photos/jjpacres/3293117576/
本題に入る前置き:?
1年半の仕事を通じた学び
? Railsの検索処理が色々あるの
を実感
? 検索処理について深掘りすると
仕事の幅が広がる
?dliban?
https://www.?ickr.com/photos/dliban/1747257576/
ということで検索系の処理に
ついて3つのステップで解説
これからお話するRailsの構成は以下のような感じ
ruby 2.2.2?
source 'https://
rubygems.org'
gem 'rails', '4.2.0'
# 省略
gem ‘ransack'
?
#以下は本来不要(おまけのネタの
ため設定)
gem 'elasticsearch-rails'
gem 'elasticsearch-model'
class InitSchema < ActiveRecord::Migration
def up
create_table "items", force: :cascade do |t|
t.string "name", limit: 255
t.string "url", limit: 255
t.integer "price", limit: 7
t.integer "sale_price", limit: 7
t.text "description", limit: 65535
t.datetime "created_at"
t.datetime "updated_at"
end
end
end
class Item < ActiveRecord::Base
end
Gem?le db/migarte/001_init_schema.rb
app/model/item.rb
STEP1: ?nd系
Photo By peter burge
https://www.?ickr.com/photos/peterburge/14441995464/
?nd系
class ItemsController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# 中略
private
def set_item
@item = Item.find(params[:id])
end
end
? 特定の条件にマッチする値を抽出する時に利用
? ./bin/rails generate sca?old itemとかすると自動的に生成さ
れる
@item = Item.find_by_id(params[:id]) # 特定のIDにマッチするアイテムを抽出?
@item = Item.find_by_name(params[:name]) # 特定の名前にマッチするアイテムを抽出
? ?nd_by_カラム名という書き方もできる
? ?nd_by???はたくさんあるので、以下Qiitaの記事がわかりや
すい
? http://qiita.com/jnchito/items/2b7d64851665071ed6e6
STEP2: where
Photo By peter burge
https://www.?ickr.com/photos/peterburge/14441995464/
where基本
?特定の条件にマッチする値が1つ以上抽出される
?配列で値が返ります
Item.where(price: 1998)
=> [#<Item:0x007fa44dd9b9f0
id: 1438,
price: 1998,
#<Item:0x007fa44dd9b888
id: 1445,
price: 1998
]
?配列で値が得られるのでその値に対する処理もや
りやすい
exclude_list = ['トップス']
Item.where(price: 1998).select{|item| item unless exclude_list.include?
(item[:name])}}
where複数条件指定
?whereの引数をハッシュで渡すことで複数条件指
定ができます
Item.where(price: params[:price], sale_price: params[:sale_price])
=> [#<Item:0x007fa44dd9b9f0
id: 1438,
price: 1998,
#<Item:0x007fa44dd9b888
id: 1445,
price: 1998
]
?以下の書き方はセキュリティ上の問題あるので避
けましょう!
※詳しくは英語のサイトですがWhere Methodをご覧ください?
http://rails-sqli.org
Item.where(“price = ‘#{params[:sale]} AND sale_price= ‘#{sale_price}”)
whereついでにModel#scope
?よく利用する検索処理は Rails のModelの機能の
1つであるscope活用しましょう!
?意図が伝わりやすいコードになりやすい。
class Item < ActiveRecord::Base
# セール中のアイテムを抽出するためのメソッド?
scope :on_sale, -> do
where.not(sale_price: nil)
end
end
Item.on_sale
=> [#<Item:0x007fa44dd9b9f0
id: 3,
sale_price: 998
#<Item:0x007fa44dd9b888
id: 4,
sale_price: 1998
]
app/model/item.rb
STEP3: Ransack
Photo By peter burge
https://www.?ickr.com/photos/peterburge/14441995464/
Ransack
?gem
?https://github.com/activerecord-hackery/ransack
?入力フォームとの連携の仕組みが最初から整ってて便利
= search_form_for @search, {url: admin_items_path, html: {class: 'form-
horizontal'}} do |f|
%div.row
%div.col-md-offset-2
%div.form-group
= f.label 'アイテムID'
= f.number_field :id_eq, class: "form-control"
%div.col-md-offset-2
%div.form-group.col-md-1
= f.label '価格'
%div.form-group
%div.input-group.col-md-2
= f.text_field :price_gteq, size: 3, class: "form-control"
%div.input-group-addon 円以上
@search = Item.search(
price_gteq: params[:q][:price_gteq],
id_in: item_ids
)
View
Controller
Photo By Eugene Zemlyanskiy
http://www.?ickr.com/photos/pictureperfectpose/76138988/
Ransack利用時の注意
? whereと条件指定がかなり似てるので混在して利用す
る時に注意した方が良い
? whereの場合にはカラム名だけでOK
? Ransack使う場合カラム名+SQLのwhere句の
条件となる文字を指定
? 具体例を次のスライドで!
Photo By Eugene Zemlyanskiy
http://www.?ickr.com/photos/pictureperfectpose/76138988/
Ransack利用時の注意
item_ids = %w(1 2 3 4 5)
@items = Item.where(id: item_ids)
=> [#<Item:0x007fc199b42410
id: 1,
name: "#1 Item",
#<Item:0x007fc199b422a8
id: 2,
name: "#2 Item"
whereの場合 Ransackの場合
item_ids = %w(1 2 3 4 5)
@search = Item.search(id_in: item_ids)
@search.result
=> [#<Item:0x007fc199b42410
id: 1,
name: "#1 Item",
#<Item:0x007fc199b422a8
id: 2,
name: "#2 Item"
おまけ: ElasticSearch
Photo By peter burge
https://www.?ickr.com/photos/peterburge/14441995464/
ElasticSearch
? 何?
? オープンソースの全文検索エンジンでJavaで書かれてるソフト
ウェアです
? https://github.com/elastic/elasticsearch
? 採用してる会社?サービス多数
? FacebookやLinkedIn、GitHub??
? 何が出来るのか?
? 多機能で色々なことが出来ます。(詳しくは次のスライド)
? 簡単?
? 検索エンジンの仕組みの概念を理解しないと使うのは難しい
? 検索のアルゴリズムも色々あるので学習コストがとても高い
? ElasticSearch自体+Railsから利用するgemの使い方も知ら
ないといけないので???
ElasticSearch使った例
?あいまい検索っぽいもの
?Nikeという名前でデーターベースに登録されてる
?ユーザーからの検索はNikeはもちろんナイキでもヒットするようにしたい
Item.__elasticsearch__.client.indices.delete index: Item.index_name rescue nil
Item.create_index! force: true
Item.import
ナイキ, Nike
items = Item.__elasticsearch__.search(query:{term:{ 'name':'ナイキ' }})
trendwords.response
=> {"took"=>1,
"timed_out"=>false,
"_shards"=>{"total"=>5, "successful"=>5, "failed"=>0},
"hits"=>
{"total"=>2,
"max_score"=>5.9938283,
"hits"=>
[{"_index"=>"sample",
"_type"=>"item",
"_id"=>"514",
"_score"=>5.9938283,
"_source"=>
{"id"=>514,
"name"=>"Nike",
独自の辞書
ElasticSearchの設定(本当はもっとあるけど割愛)
ご清聴ありがとうございました

More Related Content

2015 12-19-ruby rails