method_missingを使ってnilを無視する
tryメソッドを使ってnilを無視できますが、tryをそもそもしたくない。
object.try(:method).try(:method)
とかやりたくないわけですよ。汚いから
NilClassでmethod_missingをオーバーライドする
class NilClass def method_missing(name, *args, &block) nil end end # どこまでも続けられるよ! # nil.map(&:id).join(',').....
これでNilClassに存在しないメソッドが呼ばれるとnilを返すのでtryなんてしなくてもnilを無視できる!
ちなみに、これはnilに対してNoMethodErrorが発生しなくなり、想定しないnilが返ってくるバグが発生した時、原因が見つかりにくくなる諸刃の剣であるため注意。
rails4.1 CHAPTCHAを使う
CHAPTCHAとは
入力フォームで機械的な投稿を防ぐために、画像の読みにくい文字を入力して認証させるやつ。
↓こんなの
simple_captchaが便利そう
というかsimple_captchaしか見当たらない。
正しく動作させるまでに結構手こずった。手順通りやってもダメじゃん。
captcha画像の404エラーとか、
Error while running convert: sh: convert: command not found
みたいなエラーでつまづいている人に役立つかも。
インストール方法
Macでの方法
1 brew install ImageMagick
2 brew install ghostscript
3 Gemfileに以下を追記してbundle install
gem 'simple_captcha2', git: 'https://github.com/pludoni/simple-captcha.git', require: true
ここでインストール終了。
設定方法
1 rails g simple_captch を実行
2 rake db:migrate を実行
3 ApplicationControllerに以下を追記
include SimpleCaptcha::ControllerHelpers
4 表示させたいViewに以下を追記
<%= show_simple_captcha %>
5 実際に表示されていることと確認して終了
実際に機能させる
1 実際にCAPTCHAを利用するコントローラで以下の処理を追記
if simple_captcha_valid? # 認証成功したときの処理 else # 認証失敗したときの処理 end
カスタマイズする
1 CAPTCHAの文字入力フォームにクラスを適用したい場合
<!-- こうではなく <%= show_simple_captcha %> --> <!-- こう --> <%= show_simple_captcha(input_html: { class: 'classname' }) %>
bootstrap等でデザインを統一しているとき等に役立つ
2 生成される画像の複雑さをあげる
config/initializers/simple_captcha.rbを作り以下を追記
SimpleCaptcha.setup do |sc| # 画像のサイズ default: 100x28 sc.image_size = '200x80' # 文字列の長さ default: 5 sc.length = 6 # 画像のスタイル 固定よりランダムが良い sc.image_style = 'random' # 画像のグニャグニャ感のレベル(上下の揺れ) default: low # possible values: 'low', 'medium', 'high', 'random' sc.distortion = 'high' # 画像のグニャグニャ感のレベル(立体感のある揺れ?)default: medium # possible values: 'none', 'low', 'medium', 'high' sc.implode = 'medium' end
Ruby ファイルの種類からcontent-typeを取得する
拡張子からの判断ではなく、ファイルの内容で判別したい
具体的に言うと、jpegファイルを拡張子をpngにして保存したときも"image/jpeg"が取得したい ということ。
MIME::Typesを使うと拡張子から判断するため、上記の場合"image/png"が取得されてしまう。
ruby-filemagicを使う
1.まず下記をインストール
// for Mac brew install libmagic // for CentOS yum install file-devel
2.gemをインストール
gem install 'ruby-filemagic'
3.下記で取得
path = 'test.png' # 実際のファイルはjpeg FileMagic.new(FileMagic::MAGIC_MIME).file(path).split(';').first # =>image/jpeg
RSpec before(:all)とbefore(:each)の違い
はまったのでメモ。
大きな違いは実行順番ではない
自分もそうなんですが:allと:eachの違いは実行順番だけだと思っていましたが実際は違います。 例えば下記のようなテストの場合
describe Account do context '#signin' do context 'メールアドレスとパスワードが一致していたら' do before(:all) @mail = 'hoge@mail.com' @password = '1234' Account.create(mail: @mail, password: @password) end after(:each) Account.delete_all end it 'サインイン出来る' do # テスト処理 end end end end
この処理はサインインできることをテストするために、必要なアカウントをbefire(:all)で用意し、 テスト実施後に用意したデータを消すつもりで書いています。
しかし消えません。
いろいろ調べた結果、:allと:eachは実行順番以外の違いがあることが分かりました。
:eachは変数の書き換えやトランザクション発行を全てそのスコープ内限定(今回だとit サインイン出来る)で利用出来るようにしています。
:eachで用意したデータは特定のitでのみ利用するいう意味合いを含むためこのような仕様になっているのかと思います。
ではなぜ用意したデータが消えないかという、after(:each)で発行したdelete_all(delete処理)が他のテストに影響しないよう、丁寧にロールバックされているためです。 :eachでのトランザクションは全てロールバックされるので、before(:each)でAccount.createすれば、特にdelete処理をする必要も無かったということで一件落着しました。
Rails4.0でJasmineを使う
Jasmineとは
RSpecライクなjavascript用のテストライブラリです。 javascriptでも当然単体テストが必要ですがどのようなテストがあるのか分からなかったため、調べてみたらjasmineというのが引っかかりました。 今回はそのjasmineを導入します。
bundle install
Gemfileに以下を追加しbundle installを実行します。
group :development, :test do gem 'jasmine' gem 'jasmine-rails' gem 'jasmine-jquery-rails' end
テストの例を作成
ターミナルで以下を実行
rails g jasmine:install rails g jasmine:examples
サンプルファイルが生成されます。
実行
ターミナルで以下を実行
rake jasmine
実行するとテスト実行用のウェブサービスが起動されます。 デフォルトだとhttp://localhost:8888でアクセスできますのでアクセスします。 アクセスするとコンソール画面が表示されテスト結果が表示されます。 ここまでできればjasmineがrailsで実行できるようになったと言えます。
補足
rake jasmine:ciでコンソールでのテストが実施できます。
IEnumerable<T>にEachメソッドを生やす
List<T>にはForEachメソッドがあるんだけどIEnumerable<T>には無いから作った。
public void Each<T>(this IEnumerable<T> values, Action<T> action) { foreach(var v in values) action(v); }
使い方
var list = new[]{"1","2","3"}; list.Each(x=>Console.WriteLine(x));
下記が通常のforeachを使った場合ですが、foreachよりコンパクトになり良い。
var list = new[]{"1","2","3"}; foreach(var x in list) Console.WriteLine(x));