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

リア充爆発日記

You don't even know what ria-ju really is.

Railsで検索フォームのバリデーションをかける

検索フォームの入力値もちゃんとバリデーションかけないと脆弱性のスクツになってしまいます。

RailsCastにひとつの答えが載ってた。
http://railscasts.com/episodes/111-advanced-search-form-revised ※有料記事
かんたんにまとめると、検索をひとつのリソースとしてみなすんだ、と。検索用のコントローラ作って検索フォームをモデルにしちゃって検索条件もセーブしちゃえば、いいじゃん。でもそれはDBが肥大するから定期的に消そうぜ!的なアプローチ。

これはこれで、検索の使われ方とかも調査できるからいいと思うんだけど、とりあえず調査したい感じのものじゃないし、定期的に消すとかその辺がめんどうなので、モデルにするところだけ採用したいな、という話。

これをtableless modelというのがスタンダードかどうか知らないけど、とにかくtableless modelはActiveModelを使えば実現できる。
http://railscasts.com/episodes/219-active-model
※Rails2以前はダメポだと思われ。

で、こんな感じになる。
model

class Search
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  MAX_LENGTH_WORDS = 1000

  attr_accessor :words,

  validates :words, length: {maximum: MAX_LENGTH_WORDS}

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def persisted?
    false
  end
  def something
    @something ||= find_something
  end

private
  def find_something
    something = Something.where(status: Status::PUBLIC).limit(10)
    something = something.where(words: words) if words
    something
  end
end

controller

~snip~
      search = Search.new(params[:q])
      if search.valid?
        something = search.something
      else
        respond_with search, status: :unprocessable_entity and return
      end
~snip~

時間がないから1行1行の説明はしないので、詳しくはさっきのRailsCastを読んでちょ。
これはWebAPI用に作ってるのでHTMLのFormでちゃんと動くかはまだ試してないけど。

テストももちろんフツーに書けるよ!

結界師 (1) (少年サンデーコミックス)

結界師 (1) (少年サンデーコミックス)

結界師 コミック 全35巻 完結セット (少年サンデーコミックス)

結界師 コミック 全35巻 完結セット (少年サンデーコミックス)