rubyのfixture replacementについての文句
何年ぶりなんだろ。おひさしぶりです。
7年ぶりの投稿は超初心者ネタ。 rubyのfixture replacementってみなさん何使ってますか? まぁ factory_bot ですよね。わたしもそうです。
factory_botって真面目にassociationを表現しようとするとなんか直感的に感じない。。。
class Product < ApplicationRecord has_many :items end class Item < ApplicationRecord belongs_to :product end
というような関連のモデルがあるとき、
FactoryBot.define do factory :poduct, class: 'Product' do items [:low_item, :high_item] # こんな感じに使いたい! end factory :low_item, class: 'Item' do end factory :high_item, class: 'Item' do end end
としたいんですよ。
でも、factory_botのドキュメント では
FactoryBot.define do factory :poduct, class: 'Product' factory :low_item, class: 'Item' do accosiation :product, factory: :product end factory :high_item, class: 'Item' do accosiation :product, factory: :product end end
このようにやりたいことの逆の定義になるっぽい。
ruby tool box で他のライブラリを探してみたんですが、factory_bot一強なんですね。うむー。
herokuにデフロイした時のメモ
2013年7月14日 タイムゾーンに関する記述を追加しました。
概要
無職中で暇なので、Herokuを使ってみました。Herokuはアカウントだけ作って触ったことなかったので、ドキドキでつまずきまくったけど、実質1時間くらいでデフロイできました。たぶん、普通にrails開発をしていて以下のことをすればHerokuへのデフロイは完了すると思います。
参考URL
他の参照したページもあるのですが、内容が重複していたり、情報として古くなったものもあったので、主観で覚えときたいリンクだけを残しました。
Herokuにデフロイする時に特別にした作業
heroku-toolbeltをインストールしてHerokuにログイン
昔は heroku
っていうgemを使ってたような話を聞いたことがあるけど、今はコマンドラインツールをHerokuが提供してくれているらしい。
brew install heroku-toolbelt
でインストール完了。
次に
heroku login
ってコマンドを打つと、
Enter your Heroku credentials. Email: hogehoge@email.com # Herokuでログインしているメールアドレス Password (typing will be hidden): # Herokuのパスワード Found the following SSH public keys: # ~/.ssh/にあるファイルを自動的に探してくれる。複数ある時はどっちを使うか聞かれる。 Which would you like to use with your Heroku account? 2 Uploading SSH public key /Users/hoge/.ssh/id_rsa_hogehoge.pub... done Authentication successful.
こんな感じで
- ログイン
- sshの登録
をしてくれる。
環境変数の扱い
Herokuコマンドで環境変数を設定することをよく書かれているけど、僕はfigaroっていうgemを使っていたので、
rake figaro:heroku
ってすると開発環境で使用している環境変数をHerokuに設定してくれます。
sqlite3をdevelopment、test グループに移動して pg をproductionにした
これは有名なことなので詳細は割愛。
rubyのバージョンを指定した
本日(2013年7月1日)現在、Heroku上のデフォルトのrubyバージョンは2.0です。
ruby1.9.3を開発時使用していたら、Gemfileに
ruby "1.9.3"
と書きましょう。
rails_12factor gem を入れた
HerokuのGetting Started with Rails 4.x on Heroku と公式に書いてあるのでそのまんま入れといた。
上記リンクには「静的なasset機能とlogの機能をうまく処理してくれる」っぽいことが書かれていた。
config.assets.initialize_on_precompile = false
を追加した
知っておきたい!Herokuを使う上では当たり前?の16の常識 にとにかく「書いとけ」とのこと。
タイムゾーンを設定した
アプリケーション内のタイムゾーンを設定します。
しかし、これをしても heroku logs
で見れる時刻は設定したタイムゾーンを示してくれません。
heroku config:add TZ=Asia/Tokyo
他の記事で書かれていなくて、心配だったこと
開発時はsqlite3を使っていたので、database.ymlは全く変更していませんでした。当然production環境の設定もsqlite3です。 dbの接続情報もHeroku上では公開されてなさそうだしどうしたものか。。。
しかし、この心配は杞憂に終わりました。
普通にHerokuにpushすると
-----> Writing config/database.yml to read from DATABASE_URL
とログに出ていました。Herokuが勝手にやってくれるらしい。
あやふやなこと
Herokuを使う時、アセットパイプライン関係でハマるというイメージをなんとなく持っていたんだけど、とくにはまらなかった。
対策っぽいことをしていたことはしたけど、「アセットをプレコンパイルしたよー」って以下のログが出たのは
-----> Preparing app for Rails asset pipeline Running: rake assets:precompile Asset precompilation completed (49.11s)
sass-railsをassetグループから外した後にデフロイした後だった。
rails_12factorを入れたり、 config.assets.initialize_on_precompile
を false
にしたりってのは不要なのかな。。。
- 作者: 掌田津耶乃,相澤歩
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2013/03/15
- メディア: 大型本
- クリック: 7回
- この商品を含むブログ (2件) を見る
el-getのinfoディレクトリ先を確認する
el-get導入に伴って、infoディレクトリ先を指定したい。デフォルトはどこなのか?カスタマイズ出来る変数はあるのかを確認したい。
読んだソースは4fe798dbのコミット分。
el-get-installの定義から順を追ってみたけど挫折したので、ソースからinfoっぽい文字列を探す。
M-x moccur-grep-find \binfo\b .*el$
で検索すると、早速それっぽいの発見。
el-get-install-or-init-info
el-get-build.el内に定義されている。
ここをななめ読みするとどこかの .info っていうディレクトリに入れられるっぽい。斜め読みしていると後から困りそうなのでもう少し読む。 .info に入るって思った根拠はここ。
(list (list el-get-install-info (if (string= (substring infofile -5) ".info") infofile (concat infofile ".info")) "dir"))
infofile を設定している元を追う。
- infofile は let* 内。
(infofile (if (and (file-exists-p infodir-abs-conf) (not (file-directory-p infodir-abs-conf))) infodir-abs-conf (concat infodir-abs pname))))
いろいろしているけど、 infodir-abs-conf を元に設定される。
- infodir-abs-conf は pdir と infodir を結合したもの。
(let* ((infodir-abs-conf (concat pdir infodir))
- pdir は el-get-package-directory から取得している。
(pdir (el-get-package-directory package)))
el-get-package-directory
el-get-core.el内に定義されている。
パッケージ名と el-get-dir を結合したものを返す。
el-get-dir
el-get.el内に定義されている。
デフォルトは ~/.emacs.d/el-get/ 実際にel-getがパッケージをインストールする場所。
結論
el-getでインストールされるinfoは各elispがインストールされるパッケージディレクトリ配下の .info ディレクトリ配下に出来上がる。変数によるカスタマイズは出来ない。 でも、el-getでパッケージのバージョンごとのinfoの管理まで出来ることになるので、あまり問題はないでしょう。
Emacs Lispのシンタックスハイライト出来ないんですね。。。
era_ja0.2.0公開
西暦から和暦に変換するgem、era_jaをアップデートしました。
アップデートの内容
漢数字を出力出来るようにしました
今回のアップデートではフォーマット文字列に漢数字を追加しました。
こんな感じで出力出来ます。
Date.new(2013,2,11).to_era("%O%JY年%Jm月%Jd日") => 平成二十五年二月十一日
年、月、日を表すフォーマット文字列の前に %J
をつけると漢数字として認識します。年、月、日なので、当然西暦も漢数字に変換出来ます。
Time.mktime(2013,2,11).to_era("%JY.%Jm.%Jd") => 二千十三年二月十一日
バグフィックス
EraJa#to_era のフォーマット文字列で %Y
%y
などの西暦をそのまま出力する時、うまく変換出来ていない場合に対処しました。
Date.new(2013,2,11).to_era("%Y年%Jm月%Jd日") => 13年二月十一日
となっていたものを
Date.new(2013,2,11).to_era("%Y年%Jm月%Jd日") => 2013年二月十一日
と出力出来るようにしました。(あまりユースケースが思いつかないけど、、)
西暦から和暦に変換するコードを毎回ごにょごにょ書いている方はぜひお試しを!!!!
反省点など
スピードが遅い
開発のスピードが落ちちゃってますね。。。まぁやることは和暦への変換だけという簡単すぎるライブラリなので、改善するネタもあまりないんだけど。。。でも、クローンしてくれた方が出てきてくれててモチベーション上がりました。ありがとうございます!
rake releaseっていいよ
今までなんとなくbundlerの rake release
を使っていなかったけど今回のリリースで初めて使ってみました。なんで毛嫌いしてたんだろ?っていうくらい簡単にGitHubへのpushとrubygemsへのリリースが出来てしまった。食わず嫌いはイカン。
でも rake release
ってやるとtagメッセージがただのバージョン名になっちゃうんですよね。今までそのバージョンでの大まかな変更点を書いていたんだけど統一感がなくなってしまった。まぁtagメッセージってあまり見ないからいいかということで。
shared_exampleいいよ
このライブラリは僕にしてはrspecの shared_example
を多用していて、コードをいじる時に shared_example
のお陰でかなり見通しがよくなっていました。慣れてないので始め見た時は「なんだ?」って思ったんだけど概要が理解出来るとかなり捗る。
shared_exampleの置き場
リリース後の今になって思うけど、 shared_example
の置き場って spec_helper.rb でいいのかなぁ。他のコードを見てみよう。
Capybaraのtableishもどきを読む
こちらのgist で
page.find('table').all('tr').map { |row| row.all('th, td').map { |cell| cell.text.strip } }
というふうに以前のcucumberでできていたtableishをcapybaraで実現するコードが紹介されています。railsなどのwebアプリのテストで、一覧の出力順を含めたテストなどで非常に役立ちます。ただ、短いコードながら毎度毎度、読んで忘れて読んで忘れてを繰り返しているので、ちょっとした改造や、トラブルが起こった時にいっつも悩んでいたので、メモしておきます。
1行で書かれているものですが、各命令に分割して解読していきます。
解読した方法
基本的にはpryを使ってそれぞれの命令を順に実行して、APIドキュメントで情報を補足していきます。
例えばこんな感じ。
pryで止まった後
page.find('table').all('tr').class => Array
おぉArrayか、まぁ次はmapだからArrayの要素を見た方がいいのねっていうことで
page.find('table').all('tr')[0] #<Capybara::Element tag="tr" path="/html/body/div/div[2]/table/tr[1]">
というところまで、まぁ自分がつまづくところまでいって、そこから一度立ち止まってCapybara::Node::ElementのAPIドキュメントで次に呼ばれるメソッドがどこで定義されているのかとか他の情報を補足していきました。
解読
page
Capybara::Session
が入っている。ようするにwebページの情報が入っているもの。
page.find('table')
指定のタグに該当する Capybara::Node::Element
を取得するもの。なので同一ページで複数のtableタグがあると(html的に)最初のtableしかとらないんだと思う。
Capybara::Node::Element#find
というメソッドが存在しささそうで、継承やらインクルードで、このメソッドがどこで定義されているかがAPIドキュメント上見えない。ただし、定数 NODE_METHODSの中にfindという単語を見かけたので、なんらかうまくしてるんだと思う。
.all('tr')
Capybara::Node::Element#all
は Capybara::Node::Finders
で定義されている。返却されるのはArray。各要素は Capybara::Element
。
ここまでで、tableタグ内のすべてのtrタグ(見出しを含めた全行)を取得している。ここで行列相当の情報がとれているはず。
.map{|row| row.all('th, td')
.all('tr')
返却値の各要素は Capybara::Element
。なので、trタグの中にあるthかtdを取得している(各行にアクセスできる状態になっている)
.map { |cell| cell.text.strip }
cell
というのはそのもの最小単位の要素のこと。
cell.text
とするとよくわからん改行やら空白やらを含んだ文字列が取得される。 なので、 String#strip
で不要な空白などを削除する。String#strip
はrubyの標準のメソッドで前後の空白を削除するメソッド。
改造するには
こちらのgist にあるように 同じページの中にtableタグが複数あってidで取得するものを限定したい時は
page.find('table' + "#" + id)
とidを追加で指定すればいいようです。
同じようにそれぞれのレベル(その中この行は省きたいとか、このcellだけを取りたい)とかある時はそれぞれのレベルの all
を呼び出しているところに指定したclassとかidとかを指定しちゃうとうまくいきそうです。
すっきり!
SinatraでHTTPメソッドのDELETEを実現する
SinatraでHTTPメソッドのDELETEを実装する時かなりはまったのでメモです。実はもっと賢いやり方があるのかもしれないので、コメント大歓迎(基本的に僕のブログは全部そうです)。
今回は間違ったところから書きました。
使用環境
- ruby : 1.9.3-p286
- sinatra : 1.3.3
- haml : 3.1.7
- rspec : 2.11.0
- capybara : 1.1.3
- capybara-webkit : 0.13.0
です。
関係しそうなもの
Sinatraのルーティング
SinatraのreadmeのRoutesの中で get、post、put、patch、delete、optionsが指定できますっぽいことが書かれています。
Sinatraの設定で関係あるもの
SinatraのreadmeのConfigration ではmethod_overrideオプションの説明があります。この記述で、「ブラウザーがDELETEメソッドとかPUTメソッドをサポートしない場合、この設定が必要になる」っぽいことが書かれています。これを読んだ時に、「まさか最新のブラウザーがDELETEメソッドとかサポートしてないはずないだろうー」と思ったのが間違いだった。
間違ったコード
上記の調べたものから「DELETEメソッドなんて新しいブラウザがサポートしてるに決まってる」と間違った解釈をして書いたコードがこちら。
hoge.rb
class HogeApp < Sinatra::Base get "/" do # Hogeの一覧を取得 end delete "/destroy_hoge/:number" do # Hogeの削除処理 end end
index.haml
#... %a{href: "/destroy_hoge/#{hoge.number}", 'data-method' => 'delete', rel: 'nofollow' } Destroy
この場合テストは通るけどブラウザで実際動かすとエラーになる。エラーの内容を見るとDELETEメソッドでリクエストを発行しないといけないのに、GETメソッドでリクエストが発生しているようです。
修正版
method_overrideを有効にして、WebページからのPUTとDELETE の通りに書いていきます。ようするに、formタグをの中に、nameに "_method"
valueに実際送りたいHTTPメソッドを持つhiddenのinputをつけてあげるといいらしい。
hoge.rb
class HogeApp < Sinatra::Base enable :method_override # ここを追加 get "/" do # Hogeの一覧を取得 end delete "destroy_hoge/:number" do # Hogeの削除処理 end end
index.haml
#... %form{action: "/destroy_hoge/#{hoge.number}", method: :post, name: "destory_hoge"} %input{ type: 'hidden', name: '_method', value: 'DELETE' } %input{ type: "submit", value: "Destroy"}
おまけ
こちらの記事 link_to に :method => :delete を指定した時の動作 で
確認しましたが、railsでは link_to
からリクエストを発行する時に、javascriptで書き換えを行なっているっぽいです。railsって便利〜
WebページからのPUTとDELETEの記述で「HTML5より前のHTMLでは、フォームで利用できるHTTPメソッドはGETとPOSTだけである」っていうのは間違えなのかなぁ。
Hatena Blogへ移行してみた
はてなダイアリーからHatena Blogへ移行してみました。
今まで org-mode => hatena記法(一部変換不能) => はてなダイアリーに貼り付け という手順を踏んでいました。 貼り付け後手直しが発生したり面倒だーという理由付けを自分でして、なかなか定期的にブログを書かないでいたので、ブログの移行を考えていました。
今はやりのgithub pages とjekllyなどの静的サイトの生成ツールを使ってブログを書こうかと思ったんだけど、それは僕には敷居が高すぎる。色々とサービスを探していたんだけど、最近僕の記事にはてなブックマークをつけてくれる人やtwitterで紹介してくれる方もいらっしゃってそれはそれで嬉しいので残したい。
移行が楽で、emacsから書いた文章がダイレクトにブログに投稿出来るサービスはHatena Blogだったので思い切って移行に踏み込みました。
他の方の記事でも、同様に記法の確認をしているんだけど、僕もならってmarkdownの記法がHatenaBlogでどう表現されるか確認してみます。
確認した記法
見出し記法
emacsのmarkdown-modeで書いているので見出しはこんな感じで書いてます。
emacsで C-c C-t 2
## 見出し2 ##
emacsで C-c C-t 3
### 見出し3 ###
見出し2
見出し3
リスト記法
こう書くと
- リスト1
リスト1の中でごちょごちょ
- リスト2
リスト2の中でごちょごちょ
段落をかえてごちょごちょ
こうなる
- リスト1
リスト1の中でごちょごちょ
- リスト2 リスト2の中でごちょごちょ
段落をかえてごちょごちょ
シンタックスハイライト
一番使うやつ。
こう書くと
```ruby
array = [1, 2, 3]
array[0] # => 1
array[1] # => 2
```
こうなる
array = [1, 2, 3] array[0] # => 1 array[1] # => 2
リンク
リンクも使いますねぇ。
こう書くと
[WrapExcelはここです](https://github.com/tomiacannondale/wrap_excel)
こうなる
他の記法
とりあえず僕が使いそうなのは上記の記法なので満足ですね。ほぼmarkdownの記法は使えるっぽいです。 詳細は はてなブログで「Markdown記法一覧」を書いてみるテスト を見てもらうとわかると思います。