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

vaguely

和歌山に戻りました。ふらふらと色々なものに手を出す毎日。

DBに登録したSlimのコードを出力するとか

Ruby Sinatra

Slimのサニタイジング

しばらくハマっていた、DBやController(app.rb)でSlimやHTMLのコードをviews/blog.slimで表示しようとすると、 HTMLがエスケープされてタグがそのまま表示されてしまう問題について。

結論から書くとSlimの仕様でした、という話です。

原因

Slimでは、Rubyの変数を「=」で渡した場合は自動でサニタイジングされ、それをキャンセルするには「==」で渡す必要があります。

1.「=」で渡した場合

app.rb

get '/' do
  @redText = "<font color=\"red\">テストです</font>"
  slim :blog
end

views/blog.slim

= @redText

実際の表示

<font color="red">テストです</font>

2.「==」で渡した場合

app.rb

「=」で渡した場合と同じです。

views/blog.slim

== @redText

実際の表示

テストです
  • ※上記は「<」「>」を全角記号にしていますが、実際のコードでは半角で記述しています。

Slimを使う

上記の例ではHTMLを使っていましたが、これをSlimに変更するにはもう一手間。

app.rb

get '/' do
  @redText = "font color=\"red\" テストです
  slim :blog
end

views/blog.slim

== slim(@redText)
  • gem「redcarpet」を使ってMarkdownを使用する場合も、Markdownの形式で元データを作り、blog.slimで「== markdown(@redText)」とやれば同様に表示できます。

DBにSlimのコードを保存して、それを表示する場合

基本DBにコードをそのまま入れてやれば良いのですが、インデントはハードタブ「 」で入力されている必要があり、半角スペースだと正しく表示されなかったり、エラーに成ったりします。

サイト内検索

さて、それなりには機能が揃ってきたこのサイトですが、記事が増えてきたら検索をしたいところ。

今回はサニタイジングなどは考えず、とりあえず検索窓に入力した文字で記事を検索し、メインカラムに該当の記事を表示できるようにします。

検索窓

まずは検索窓を右カラムに追加します。

views/layout.slim

form action='/search' method='GET'
  input type='text' name='q'
  input.btn type="submit" value="検索"

ActiveRecordでLike検索

検索窓に入力したキーワードを使って記事タイトル、記事を対象にデータを検索します。

通常のSQL文では「WHERE カラム名 LIKE '%クエリ%'」と記述するところです。
ActiveRecordでは前回と同じく「Model.arel_table」を使い、matchesの引数にクエリを渡します。

app.rb

require 'sinatra'
require 'sinatra/base'

require 'will_paginate'
require 'will_paginate/active_record'
require 'will_paginate/view_helpers/sinatra'

require './models/dbAccessers'

class MainApp < Sinatra::Base
  get '/search' do
    strQuery = params[:q]
    # 前方一致・後方一致に対応するため%を付ける.
    strQuery = "%" + strQuery + "%"

    searchCriteria = Post.arel_table
    # 入力されたクエリがタイトルor本文に合致していたら取得.
    @pager = Post.includes(:taglinks).where(searchCriteria[:post_title].matches(strQuery).or(searchCriteria[:post].matches(strQuery))).order(post_id: 'desc').paginate(:page => params[:page], :per_page => 5)
  end
end
  • (検索窓にクエリを入力してボタンを押して)「localhost:9292/search?q=クエリ」というURLにアクセスした時に実行します。
  • 上記はDBを検索しているだけなので、実際には取得した値をViewに渡してやる必要があります。

課題

  • 入力されたクエリをサニタイジングして、任意のコードがユーザーから実行できないようにする
  • URLの「q=」の部分などに「%」のような半角記号を直接入力するとエラーが発生するため、その対処(サーバー側での対処?)
  • 検索結果のページで、件数などをページ上部に表示したり、0件の場合は結果がない旨のメッセージを表示する

参考

Slimのサニタイジング

ActiveRecordでLIKE検索・OR検索

SQL LIKE検索

Slim