rspec内でCSFR対策を有効にする
railsでpost送信を行う際に、画面を経由しないリクエストには422が返却される。
これはrailsのCSRF対策である、ActionController::Base.allow_forgery_protection
がtrueになり、ApplicationControllerの protect_from_forgery with: :exception
で、CSRFチェックでNGだった場合に例外を発生させる設定になっているため。
rspecで使われるtest環境ではallow_forgery_protectionがfalseになっているが、rspec時にCSFR対策を有効にするには
ActionController::Base.allow_forgery_protection = true
とする。
describe 'createの確認' do let(:params) { FactoryGirl.build(:post).attributes } before { ActionController::Base.allow_forgery_protection = true } after { ActionController::Base.allow_forgery_protection = false } it 'レスポンスに422が返されること', autodoc: true do post '/api/v1/posts/create', params expect(response.status).to eq(422) expect(response).not_to be_success end end
direnvを使ってディレクトリごとの環境変数設定を行う
direnvを使って、そのディレクトリ下でのみ有効な環境変数を設定する。 前提mac。
$ brew install direnv
インストール後、.bashrcまたは.bash_profileに以下の1行を追加
# bashの場合 eval "$(direnv hook bash)"
あとは環境変数を設定したいディレクトリに以下のコマンドで設定ファイルを作成する。
$ direnv edit .
そうすると、.envrcファイルが出来上がるので、中身を編集する。
# 一例 export HOST_URL='http://localhost:3000'
エラーが発生する場合はdirenv allowコマンドを実行する。
注意点として.envrc内にgit管理されるとまずい情報が載っている場合は.gitignoreに忘れずに含めること。
railsのモデルに、特定の条件下で動くvalidationを追加
ifを使用した条件分岐
例えば、bという項目がtrueの場合のみaの値は必須にしたい、とかあると思う。
with_optionsメソッドを使用して以下のように実装することができる。
class Post < ActiveRecord::Base # ifオプションで条件に合致する場合のみvalidatesを実行(published?はメソッド名またはmodelのboolean項目) validates :name, presence: true if: published? # 複数valitatesをまとめたい場合はwith_optionsを使用 with_options if: :published? do validates :name, presence: true validates :category, presence: true end # unlessで条件に合致しない場合のみvalidatesを実行 # lambdaを使うことで複数条件を指定できる with_options unless: -> { :hoge? || :foo? } do validates :name, presence: true end end
ただし、この場合、with_optionsブロック内部で更にif: を使用してしまうと、
内部のif条件の場合にしかvalidatesが実行されなくなる。
# hogeの時しかwith_options内部が実行されない with_options if: :published? do validates :name, presence: true validates :category, presence: true, if: hoge end # with_optionsで定義したものと逆のもの(この場合はunless)を使用すれば問題ない with_options if: :published? do validates :name, presence: true validates :category, presence: true, unless: 'hoge.blank?' end
ネストしたvalidationを記載するなら、メソッドを一つ作って指定した方が良さそう。
validates :name, presence: true, if: :require_validation? def require_validation? return true if aaa? && bbb? false end
onを使用した条件分岐
例えば新規登録(create)の場合のみバリデーションをかけたい時は、onオプションを使用する。
class Post < ActiveRecord::Base # createの時のみ実行 validates :name, presence: true on: :create # if同様with_optionsを使用できる with_options on: :create? do validates :name, presence: true validates :category, presence: true end # こうすることで、pattern_hogeコンテキストが渡された時のみvalidatesが実行される validates :hoge, presence: true, length: { maximum: 3000 }, on: :pattern_hoge end
class PostsController < ApplicationController def hoge # pattern_hogeコンテキストを指定 post.save(context: :hoge.save(context: :pattern_validation)) end end
railsでenumを使う
modelに記述する。
class Post < ActiveRecord::Base enum status: { created: 0, drafted: 1, canceled: 2 } end
こうすることで、Post.statusesとして、各Enumにアクセスすることができる。
pry(main)> Post.statuses # => {"created"=>0, "drafted"=>1, "canceled"=>2} pry(main)> Post.statuses[:drafted] # => 1 pry(main)> @post = Post.new pry(main)> @post.status = Post.statuses[:drafted]
また、インスタンスに対して、enumの各要素をメソッドとして使用することができる。
pry(main)> @post = Post.new pry(main)> @post.status = Post.statuses[:drafted] pry(main)> @post.drafted? # => true pry(main)> @post.canceled! pry(main)> @post.canceled? # => true pry(main)> @post.drafted? # => false
modelとの関連付けはせず、Enumとしてだけ使用したい場合、
locales下のymlファイルに記述する方法もあり。
ja: Enum: status: created: 0 drafted: 1 canceled: 2
pry(main)> Enum.codes(:status) => ["created", "drafted", "canceled"]
選択肢が限られているセレクトボックスの検証とかで、inclusionと合わせて使えそう。
シェルでディレクトリ内のファイルの数を調べる
例えばシェルでディレクトリ内に何ファイル存在するか調べるには以下の方法でチェックをする。
ls -FU1 '対象のパス' | grep -v / | wc -l
ざっと解説すると、lsの結果をgrepに渡し、grep -vで不要な情報を削除し、
wcコマンドにわたし、数をカウントしている。lsオプションは以下の通り。
- -F:ディレクトリが存在する場合は/を付与して表示する。
- -1:lsの結果を1行ずつ表示
- -U:lsの結果をソートしない(速度向上)
上記の例だとディレクトリを省いてファイルの数を調べている。
また、wcコマンドは、渡されたファイルのバイト数も表示するため、
-lオプションは、渡されたファイルの個数のみを表示させている。
ブックマークレットでフォームに自動的に入力するスクリプトを作りたい
テストとかで画面に値を入力する場合、 繰り返しテストをしていると、
毎回フォームに値を入力しないといけないのがダルい。
ブックマークレットで1クリックだけでフォームに値をセットできるスクリプトを作りたい。
とりあえずフォームの要素に値をセットする方法。
javascript:(function(){ document.getElementById("srchtxt").value = "てすと";}())
ついでに画面内のID全て取得するブックマークレット
javascript:(function() {var elements = document.getElementsByTagName("input");var i = 0; var ids = "";for (i = 0 ; i < elements.length ; i++){ids += elements[i].id + "\r\n";}alert(ids)}());
コマンドプロンプトでgrep
コマンドプロンプトでgrepするならfindstr
Windowsのコマンドプロンプトでgrepと同じことをしたい。
findstrコマンドが良さげ。
findstr [オプション] "検索対象文字列" "検索対象のファイル"
以下よく使いそうなオプション
デフォルトでは正規表現での検索をしてくれないので、/Rオプションを使用する。
/I 大文字小文字を区別しない /S ディレクトリを再帰的に検索する /R 正規表現を使用する /C 空白を含む文字を検索する場合に指定する /N 一致した行数を表示 /V 指定した文字を含まない行をすべて表示
使用例
カレントディレクトリ以下で、”This is〜"という文字が含まれている箇所をresult.txtに出力する。
findstr /R /S /C "This is.*" * > result.txt