読者です 読者をやめる 読者になる 読者になる

hotoolong's blog

Railsやvimや気になったことを綴ってます

Rails4.2でlike句のサニタイズをする

ruby2.2 rails4.2

2016年はじまってもう2月になってしまいました。 遅ればせながら、あけましておめでとうございます。

昨年から相当ハードなスケジュールでなかなかブログが書けてないですが、 今年はもう少し書く時間を確保したいところ。 頑張ります。。

今日のお題は SQLでLike句を使う場合に RailsActiveRecordを使ってwhere句

Hogehoge.where('name LIKE ?', "%#{args[:name]}%") 

の様な書き方をするケース もしくはscopeでArelに設定して

scope :by_name, ->(name) {
  where(arel_table[:name].matches("%#{name}%"))
}

の様な書き方もよく見かけますが、 like句に対してサニタイズするのを忘れてしまうこともあります。

Rails4.2からサニタイズするメソッドが利用できるようになってます。 http://apidock.com/rails/v4.2.1/ActiveRecord/Sanitization/ClassMethods/sanitize_sql_like

def sanitize_sql_like(string, escape_character = "\\")
  pattern = Regexp.union(escape_character, "%", "_")
  string.gsub(pattern) { |x| [escape_character, x].join }
end

sanitize_sql_likeを使って 先ほどの処理が

Hogehoge.where('name LIKE ?', "%#{sanitize_sql_like(args[:name])}%") 
scope :by_name, ->(name) {
  where(arel_table[:name].matches("%#{sanitize_sql_like(name)}%"))
}

の用に書くことができます。 便利ですね。

+=はメソッドじゃない

ruby2.2 ruby

演算周りの処理をまとめていた時にsendで呼び出せると 綺麗にリファクタリングできるかなとおもい調べていると

1.send(:'+',3)
=> 4
1.send(:'+=',3)
NoMethodError: undefined method `+=' for 1:Fixnum

NoMethodErrorになってしまったのですが、Google先生に聞いいてみてもなかなかみつけにくかったのですが、

Rubyのリファレンスの演算子式の自己代入に記載がありました。

演算子式 (Ruby 2.0.0)

&&, ||以外は

  式1 = 式1 op 式2 

に置き換わるそうです。 基本的なところなんですね。。

Rubyの便利メソッド Kernel#Array

ruby2.2 ruby

Kernel#Arrayは引数で受け取ったものを配列に変換してくれるメソッドなのですが、 意外に便利です。 引数で受け取ったいろいろなオブジェクトを配列にして返却してくれます。

module function Kernel.#Array (Ruby 2.2.0)

試してみると

Array(nil) #=> []
Array("fefe") #=> ["fefe"]
Array(11) #=> [11]
Array([1,2,3]) #=> [1, 2, 3]
Array({key: :value, key2: :value2}) #=> [[:key, :value], [:key2, :value2]]
Array(1..10) #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

rdocでは

Returns arg as an Array.

First tries to call to_ary on arg, then to_a.

arg に to_ary, to_a のいずれのメソッドも定義されていない場合は 一要素の配列 [arg] を返します

となっているので

メソッドの中身は以下のようなものになってるはず。(推測)

object.respond_to?(:to_ary) ? object.to_ary : object.to_a

RailsActiveSupportでもArray#wrapがあり

似たようにArrayを返却してくれるメソッドがあり、こちらは

Array.wrap(nil) #=> []
Array.wrap("fefe") #=> ["fefe"]
Array.wrap(11) #=> [11]
Array.wrap([1,2,3]) #=> [1, 2, 3]
Array.wrap({key: :value, key2: :value2}) #=> [{:key=>:value, :key2=>:value2}]
Array.wrap(1..10) #=> [1..10]

返却される内容はKernel#Arrayとはすこし違っています。

ちなみにwrapの中身は

def self.wrap(object)
  if object.nil?
    []
  elsif object.respond_to?(:to_ary)
    object.to_ary || [object]
  else
    [object]
  end
end

となっています。

RangeやHashが引数に設定されていた場合の挙動が違っているので注意が必要ですが、

使い方に応じて呼び出すと処理がスッキリして使い勝手がいいですね。

メニューバーがスッキリしてアプリが確認しやすいBartenderいらず

mac

メニューバーにアプリが増えてくると

選択中のアプリのメニューが多いものになると隠れて大変ですね。

www.macbartender.com

Bartenderはまとめて拡張メニューのようなものが追加されて使えますね。

Try for 4 weeks

ということでしばらく使っていたのですが、

お試し期間が終わり購入しようかなと思ったら

Buy Now for $15

って15ドル。。

別時ケチる気はないのですが、、

15ドルだったらもうちょっといいアプリあるんじゃないかなと思い調べてみると

apple-products-fan.seesaa.net

これいいですね。

逆転の発想!?

Shift+スペースは半角入力で使っているので少しまだ慣れないのですが、 設定で変更もできるのでしばらく試しながら使っていこうかと思います。

Macでmysqlのサービスの起動停止

mac mysql

MacMysqlサービスの上げ下げはあまりしないのでよく忘れます。 brewでインストールしてると/usr/local/bin/にmysql.serverを作ってくれるそうです。

-> % which mysql.server
/usr/local/bin/mysql.server
-> % mysql.server stop
Shutting down MySQL
.... SUCCESS!

-> % mysql -uroot
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)

-> % mysql.server start
Starting MySQL
. SUCCESS!

あまり動かしてないのでよく忘れますね。。 間違ってserviceコマンド叩いてしまう。。

Railsバージョンアップメモ

rails

4.2系も続けてバージョンアップされているので ココらへんでメモ

やることは

  • Gemfileのrailsバージョン変更
  • bundle update
  • bundle install
  • ./bin/rake rails:update
  • テストを流してエラー箇所を修正

bundle updateはまとめて gemのバージョンを上げてしまうので、 上げたくないものは事前にGemfileの書き方を変更しておいたほうがいいかもしれない。

テストはrspec、minitestになるかとおもわれるが どちらにしてもバージョンアップを考えると整備してるほうが比較的簡単にバージョンアップできる。 もう少し整備しないといけないかな。

unicornに移行メモ

rails

Apache → Passenger 環境 を unicorn に入れ替える

Gemfileに gem 'unicorn' を追加

bundle installする

bundle binstubs unicorn

unicornunicorn_rails を bin配下に作成

init.dに起動シェル作成しておいて

${RAILS_ROOT}/bin/unicorn_rails -c config/unicorn.rb

などで呼び出せるようにしておく

apacheからSSLでうまく通信できないのでhttp.confに

RequestHeader set X_FORWARDED_PROTO 'https'

を追加 Proxyの設定も追加する

ProxyPass http://hogehoge.com:4000
ProxyPassReverse http://hogehoge.com:4000

これらを設定に追加すればOK あとはチューニング