no_picture

re: Rails update時に値を変更して更新したい

友人のブログ記事へのレスです。 JunkBox~主に個人的防備録~: Rails update時に値を変更して更新したい。について。 さすがにやってることがまわりくどい。コメント欄だと返信がつらいのでここにかく。 まず、元の内容を引用します。 たとえば、保存時10円単位で四捨五入して保存したい場合。 ついでに登録日を1日ずらす。 日付型の項目は、年、月、日、時、分、秒と別れてパラメタに入ってくるので、扱いづらい。ので、一旦モデルに突っ込んで処理し、その後ハッシュに変換する。 def update # パラメタを一旦モデルに突っ込む tmp = Syohin.new(syohin_params) # 金額を10円単位で丸める tmp.kingaku = tmp.kingaku.round(-1) # 日付型の登録日を1日ずらす。 tmp.record_datetime = tmp.record_datetime + (60 * 60 * 24) # モデルをハッシュに変換する。 tmp2 = tmp.attributes # 不要なキーを削除 ["id","created_at","updated_at"].each do |key| tmp2.delete(key) end #updateに突っ込む respond_to do |format| if @syohin.update(tmp2) format.html { redirect_to @syohin, notice: '更新完了' } else format.html { render :edit } end end end わざわざ一時的な新しいモデルをつくっているけど、updateメソッドのsaveしなバージョンのメソッドがある。assign_attributesメソッドである。 def update @syohin.assign_attributes(syohin_params)

no_picture

Rails 4.2.0 beta1 ちょっとだけ見たのでメモしとく。

Rails 4.2.0.beta1 が出てるよね。 Riding Rails: Rails 4.2.0 beta1: Active Job, Deliver Later, Adequate Record, Web Console betaが出ると試したくなるのでアップデートしても問題ないものをアップデートして遊ぶ。 先に結論 詳細とかあとで述べる。 Gemfile に追加とか変更とか。 gem 'rails', '4.2.0.beta1' gem 'sass-rails', '~> 5.0.0.beta1' gem 'web-console', '~> 2.0.0.beta2' group :development, :test do gem 'byebug' gem 'web-console', '~> 2.0.0.beta2' end gem 'rails-html-sanitizer', '~> 1.0' config/application.rb に追加 config.active_record.raise_in_transactional_callbacks = true config/environments/development.rb に追加。 config.assets.digest = true rails new したときの違い rails new してときの生成されるファイルの違い下記の方法で確認した。 $ rails _4.2.0.beta1_ new --no-rc hoge $ mv hoge 4.2.0.beta1 $ rails _4.1.5_ new --no-rc hoge $ mv hoge 4.1.5 $ diff -ur 4.1.5 4.2.0.beta1/ 全文はGistに貼った。 まず gem 関連 web-console と byebug と rails-html-sanitizer が追加されてる。 その他は、バージョン調整されてるだけ。 debugger はたぶん ruby 2.1 だと動いてないし、web-console を使うようになったので、byebug も追加された感じがする。よくしらん。 rails-html-sanitaizer は sanitize ヘルパーが追加できるらしい。HTMLタグがとりのぞけて独自のルールはScrubberを作ることで調整ができる模様。 以下、それ意外の抜粋。 onfig/application.rb + # For not swallow errors in after_commit/after_rollback callbacks.

no_picture

LT駆動開発で とある我馬の非公式というLTをした

LT駆動開発06 でライトニングトークをした。 我馬というラーメン屋のウェブサイトが更新情報のフィード配信してないので、勝手に応援しているという話をしました。 とある我馬の非公式(ファンサイト) 折角なのでフィードの存在を知らない人もいるかもしれないので、簡単に説明しつつ、どうやってフィードをつくったのか説明しました。 とりあえず、季節のラーメンはアツいので広島には3ヶ月に一度程度いらっしゃると良いと思います。 関連 とある我馬の非公式(ファンサイト) 我馬 eiel/gaba · GitHub eiel/gaba.eiel.info · GitHub

no_picture

ActionView 単体で slim を使ってみる

「ActionView を単体で使ってみる」というのを書いたので、ついでにいろいろ試してみる。その1。 誰が得するのか謎だけど ActionView だけで slim を使うことを試みてみました。 action_viewを require して、 action_pack を require して、 slim を require すれば使えます。 用意したファイル views/prefix/slim.html.slim p | Hello, #{@name} views/layout/appliacation.html.erb -- <%= yield %> -- require 'action_view' require 'action_pack' require 'slim' lookup_context = ActionView::LookupContext.new('./views') lookup_context.cache = false # ActionPachk を読まなくて済む魔法 view_context = ActionView::Base.new(lookup_context) view_context.assign(name: 'eiel') ret = view_context.render(template: 'slim', prefixes: 'prefix', puts ret =begin -- <p>Hello, eiel</p> -- =end slim は temple という gem を使ってRailsに対応してました。 ActionPack はバージョン確認に利用しているだけなので、ちょっといじればなんとかなりそうですけど。 Temple::Templates::Rails もう少し詳しく 誰得感がひどいのでもうちょっと書いてみる。 Railsとの連携の処理の部分は Temple::Templates::Rails(Slim::Engine, :register_as => :slim, # Use rails-specific generator.

no_picture

ActionView を単体で使ってみる

誰が興味があるのか謎ですが、ActionView を単体で使ってみようと思います。 意外にも Rails の仕組みとか見えてくるかもしれません。 Rails 4.1 ぐらいから ActionPack から独立した記憶があります。どうでしたっけ。 テンプレートを使いたい時には erb, haml, slim などを単体で利用すればいいのであまり使う機会はないかもしれません。 雑感では、 layout 機能を使いたい インスタンス変数で値にアクセスしたい Rails が提供するビューヘルパーを使いたい あたりがメリットかと思います。 この記事のために作成したコードはこちらにおいておきます。 補足の部分は読み飛ばせるように書いているつもりです。 利用したRailsのバージョンは 4.1.4 です。 1 Hello, world まずは使ってみます。 ActionView::Base.new.render(inline: 'Hello, World!') # => Hello, world ActionView::Base のインスタンスを作成し、renderメソッドを呼びだします。 コントローラでの render メソッドはどうやらこの render メソッドのようです。 (viewで使う render もこの render ですが…) 1の補足 ActionView::Base Rails を使ってる際に erb ファイルの中で self.class を確認したことはあるでしょうか? ちょっと確認してみましょう。 <%= self.class %> <%= self.class.superclass %> #<Class:0x007f82891092e0> ActionView::Base self は無名のクラスになっていますが、そのスーパークラスは ActiovView::Base です。 ビューは ActionView::Base のインスタンスのコンテキストで実行されるわけです。ビューコンテキストと呼んでいるようです。 また、このクラスにヘルパーをミックスインすることでヘルパーとして利用できるようになります。 デフォルトのHelperはすでに include されています。 > ActionView::Base.ancestors.map(&:to_s).grep(/Helper/) => ["ActionView::Helpers", "ActionView::Helpers::TranslationHelper", "ActionView::Helpers::RenderingHelper", "ActionView::Helpers::RecordTagHelper", "ActionView::Helpers::OutputSafetyHelper", "ActionView::Helpers::NumberHelper", "ActionView::Helpers::JavaScriptHelper", "ActionView::Helpers::FormOptionsHelper", "ActionView::Helpers::FormHelper", "ActionView::Helpers::FormTagHelper", "ActionView::Helpers::TextHelper", "ActionView::Helpers::DebugHelper", "ActionView::Helpers::DateHelper", "ActionView::Helpers::CsrfHelper", "ActionView::Helpers::ControllerHelper", "ActionView::Helpers::CacheHelper", "ActionView::Helpers::AtomFeedHelper", "ActionView::Helpers::AssetTagHelper", "ActionView::Helpers::AssetTagHelper::StylesheetTagHelpers", "ActionView::Helpers::AssetTagHelper::JavascriptTagHelpers", "ActionView::Helpers::SanitizeHelper", "ActionView::Helpers::ActiveModelHelper", "ActionView::Helpers::UrlHelper", "ActionView::Helpers::TagHelper", "ActionView::Helpers::CaptureHelper"] 2 インスタンス変数を使う Rails ではコントローラのインスタンス変数がビューの中で使えます。 普段はRailsが自動でやってくれていますが、自分でインスタンス変数を設定するには assign メソッドを使います。 view_context = ActionView::Base.new view_context.assign(name: 'eiel') view_context.render(inline: 'Hello, <%= @name %>') # => Hello, eiel @name が eiel に展開されています。 ActionView::Base のコンストラクタの第2引数に渡しても設定できます。 2の補足 ActionView::Rendering コントローラがビューコンテキストに対して assign メソッドを利用して、設定します。 これは ActionView::Rendering で行われます。 この ActionView::Rendering には ActionController::Base にミックスインされていて、コントローラがビューを設定する処理などが記述されているようです。 > ActionController::Base.ancestors.map(&:to_s).grep(/ActionView/) => ["ActionView::Layouts", "ActionView::Rendering", "ActionView::ViewPaths"] ActionController::Base には ActionView::Rendering がミックスインされています。 ちなみに assign するのに使う Hash は AbstractController::Rendering#view_assign で作成されています。 def view_assigns protected_vars = _protected_ivars variables = instance_variables variables.reject!

no_picture

rails console でルーティングが生成した helper を使う

Railsで config/routes.rb に resources :users とかくと users_path users_url user_path user_url new_user_path などなどのViewで利用できるヘルパーが生成される。 このヘルパーを rails console で使うには、app オブジェクトを経由する。 例 app.users_path # => "/users" app.users_url # => "http://www.example.com/records/3.html" app.user_path(User.first) # => "/users/1" app.user_path(User.first, :html) # => "/users/1.html" なんとなく関係ない例を混ぜた。 routing helper というらしいのに helper からアクセスできない。 関連リンク ActionDispatch ってなんだろう? - 広島・岡山Ruby交流会01 - そんなこと覚えてない

no_picture

Devise で登録時にConfirmation Token が不正な値というエラー

Devise で確認メールで確認してから有効にする機能 Confirmable の機能をつかってたのだけど、トークンが不正というエラーがおきた。 この問題は devise 3.1.0 より前で、確認のために送信されるメールの内容をカスタマイズしていれば起きてるんじゃないかと思う。 DBに格納される Token の値が HMAC されるようになったらしい。 Use HMAC on tokens stored in the DB · 143794d · plataformatec/devise · GitHub そのため、画面をカスタマイズしている場合、token の取得方法が変えないといけないっぽい。 -<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %></p> +<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) %></p> 確認メールだけでなく app/views/devise/mailer 内のファイル全部変えないといけない気がする。 confirmation_instructions.html.erb reset_password_instructions.html.erb unlock_instructions.html.erb あたりですね。 蛇足 v3.1.0 ってリリースされたの9月なんだが…さっき気づいたということは…。とおもって Gemfie.lock を git log –patch Gemfile.lock して devise 検索したら、デプロイされたのは最近だった。 参考 直してから探したやつだけど。

no_picture

ActiveRecord のスコープを書くときは proc を使えよって話

ActiveRecord で scope を定義する時は、普通は以下のように書きますよね。 scope :hoge, -> { where(name: 'hoge' } 歴史的背景で、 scope :hoge, where(hname: 'hoge') とか、書いてることがあるかもしれません。 この場合、一応、問題なく動きますが、コンテキストに応じて値が変化するようなものを利用してる場合には問題が起きることがあるので、早めに修正したほうが良いかもしれません。(というか問題が起きた) 前者で書きましょう。 具体例 特に日付などを利用してると問題になりやすいかもしれません。 例えば、 scope :this_month, where(month: Date.today.month) というのは、月を跨ぐと問題になる可能性が高いです。 常にデプロイした月の結果を返すことになります。 クラスをファイルを読み込みした際に Date.today.month が評価されてしまうので、そこの値が固定されてしまいます。 scope :this_month, -> { where(month: Date.today.month) } という風に書き換えておいたほうが良いです。 年とか使ってると気づかない可能性高そうですね。怖い怖い。

no_picture

Wisper 試した

Wisper を試した。 Rails のプラグインで、依存性の管理や分離ができる。 ActiveRecord の callback だと依存の記述がモデル上になって、 Observer は本家から外れたような気がするし(うる覚え)、 ActiveSupport::Notification じゃ依存性がゆるすぎる。 でも、コントローラでかくにはちょっと処理が多すぎるし…って時に探してたらみつけたプラグイン。 やってることはどれも大差ない気がするんだけど、とりあえず、公式のサンプルコードをみてみる。 class BidsController < ApplicationController def new @bid = Bid.new end def create @bid = Bid.new(params[:bid]) @bid.subscribe(PusherListener.new) @bid.subscribe(ActivityListener.new) @bid.subscribe(StatisticsListener.new) @bid.on(:create_bid_successful) { |bid| redirect_to bid } @bid.on(:create_bid_failed) { |bid| render :action => :new } @bid.commit end end create_bid_successful が発生したときはリダイレクトして、create_bid_failed が発生した時は new を render するというのをアクションでかける。 ifの分岐がなくて、縦にコードが並んで複雑な分岐をする場合は読みやすい。 また、Listener を登録することで機能追加ができる。 create_bid_successful イベントがおきたときは、PusherLister#create_bid_successful や ActivityListener#create_bid_successful、StatisticsListener#create_bid_successful なんかも呼ばれる。 Set で保存されてるようなので順番は保証されない メインの処理をモデルで集中できて少し脇道に逸れるようなものは Listener を書いて subscribe

no_picture

config/database.yml の情報にアクセスする。

Rails の config/database.yml の情報にアクセスしたかった。 別に open して read して YAML.parse するだけなのですが、 もしかすると、 config/database.yml じゃないところを読むように設定を変えてる場合もありますからね。(ねーよ) ということで適当にリポジトリを検索したら、 Rails.application.config.database_configuration で、取り出せました。 この辺りはバージョンよって違うかもしれないので、GitHub で検索するのが良いかもしれないです。

no_picture

Rails の自動読み込みの話

広島Ruby勉強会 #034で使用したネタの文に書きなおしました。 「Rails の自動読み込み規約を支える技術」と若干煽っておりますが 以下の内容はソースコードを読んで判断したことですべて正しいとは保証できないので参考にする程度にお願いします。 というわけで、Rails の自動読み込みの話をしたいと思います。 Rails の自動読み込みを支える技術 from Tomohiko Himura ### Rails のファイル読み込みの規約 Rails には[設定より規約](http://ja.wikipedia.org/wiki/%E8%A8%AD%E5%AE%9A%E3%82%88%E3%82%8A%E8%A6%8F%E7%B4%84) という設計パラダイムが採用されています。 ファイルの自動読み込みの規約は 読み込みされていないクラス/モジュールがあった場合、名前から読み込みするファイルを判断できる というような規約があります。 例えば ``` Hoge - 'hoge.rb' を読み込む Hoge::Mogu - 'hoge/mogu.rb' を読み込む HogeMogu - 'hoge_mogu.rb' を読み込む ``` といった感じになっています。 この時、クラス名からファイル名の変換は `ActiveSupport::Inflector.underscore` が利用されます。 Rails では、自動読み込みは `RAILS_ROOT/app/models` のような `RAILS_ROOT/app/` の中のディレクトリに対し行われます。 `RAILS_ROOT/lib` とかに配置しても自動読み込みされません。 これを実現しているモジュールは [ActiveSupport::Dependencies](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/dependencies.rb) になります。 ### ActiveSupport::Dependencies Rails を使わない場合の使い方を紹介します。 ```ruby require 'active_support/dependencies.rb' ActiveSupport::Dependencies.autoload_paths LoadError: cannot load such file -- hoge/mogu ``` #### eager_autoload と auto_load!

no_picture

AbstractController を継承して遊ぶ

すごい広島 #16 で遊んだこと Rails で AbstractContrller::Base を継承して オレオレ コントローラ を作りたいと思います。 どうしてこれをしたいかというと View です。 コントローラ名とアクションに対応した View がレンダリングできるのが魅力的です。 状況としてはメールを送るわけではないので ActionMailer 使えないし、すぐに画面に表示するわけではないので ActionController はちょっと…という感じなわけです。 どんな状況かというとDBに保存する長文を作成したい時です。 書いたビューはこんな感じ。 こんにちは <%= @user %>さん <%= goodbye_helper @user %> ヘルパーも使えるようにしてみます。 ファイル名は app/views/hoge_template/goro.text.erb でコントローラ名が hoge_template アクション名 goro テンプレートエンジンは erb です。 利用には以下のように使います。 rails c の中でやったり、モデルの中で使えます。 もちろんコントローラ上でも。 template = HogeTemplate.new template.process(:goro) template.render renderの戻り値がテンプレートの出力結果になります。 最終的な出力目標は こんにちは おなまえさん おなまえさん、おやすみ を目指します。 @uesr には おなまえ が入っています。 goobye_helper はお別れのあいさつをしてくれるように実装します。 作成するコントローラ的な役割をする HogeTemplate はこのように書きたいはずです。 class HogeTemplate < ActionTemplate

no_picture

広島Ruby勉強会 #033 でやったこと - ActiveSupport CoreExt & Rails Template

広島Ruby勉強会 #033 に参加しました。 前回に引き続き ActiveSupport のCoreExt のソースコードを読んだので、面白そうなところをざっくりと紹介しました。 資料 - Rails のソースコード読んだので面白そうなところを紹介する – ActiveSupport CoreExt編 その2 あと LT しました。 rails new には --template という引数があるのでこれについて調べました。 まずはスライド。 Rails プロジェクトでスタートダッシュを決める from Tomohiko Himura このスライドを作る前に調べものした時のメモは前回の記事を Rails New した時の追加処理をかく 参加者の もりしー こと @CentBoss が 「広島Ruby勉強会 #033に遊びに行ってrails newでのtemplateを作った」 早速試してみてくれました。 rails new する時のデフォルトの引数を指定できる ~/.railsrc というものがありますが、そのなかで –template が使えるのを試してくれています。 上手くいったようです。 ここでテンプレートファイルを指定しておくと、とても楽ができます。 次回の 広島Ruby勉強会は 9月7日を予定しているそうです。 発表の練習したい方募集中だそうです。

no_picture

rails new した時の追加処理をかく

この記事はメモです。 広島Ruby勉強会 #33 で LT するのに下調べしたことを書いてるだけです。 rails new した時に --template file_or_url というオプションがあります。省略形は -m。 これを使うと、rails new した時に追加処理ができます。 「テンプレート機能」と呼びたいと思います。 何がしたいかというと rails new した時点で pry とか rspec とか cucumber とかいつも使うのを設定した状態にしたいのです。 ウェブサービスが思いついたら直ちに開発をしたいのです。 このテンプレート機能を使うものとしては Rails Composer というものがあります。 これを使うと、どのライブラリを利用するか質問されるので、回答していくと、雛形ができます。 これを自分でカスタマイズしたいので、いろいろ調べました。 役に立つかもしれないウェブページ Rails Application Templates - Rails Guide Creating and Customizing Rails Generators & Templates - Rails Guide RailsのApplication templateを使って開発の初速をあげよう! ひとつめの「Rails Application Templates」は Rails Guide ですが、Rails Guide のトップにリンクがありません。 だいぶ調べた後に気づきました。泣きたい。 ふたつめも Rails Guide ですが、機能的には Generator と同じなので参考になります。 みっつめは日本語記事。面白くまとめてあります。このメモを書いてLTをつくった後にみつけた。 つづいて、関係してきそうなクラスやモジュールを整理します。 Rails::AppBuilder Rails::Generators::AppGenerator Rails::Generators::AppBase Rails::Generators::Base Rails::Generators::Actions Thor::Actions Thor::Group Thor::Shell Thor::Invocation Thor::Base --template に指定したファイルは Rails::Generators::AppGenerator インスタンスのコンテキストで実行されます。 Rails::Generators::AppGenerator が継承してるクラスやミックスインしているモジュールのメソッドが使えると考えてください。 「instance_eval される」と書いたほうがわかりやすい人もいるとかもしれません。 rails new や rails generator には、Thor というライブリが使用されています。 bundler や Vagrant でも利用されているそうです。 もっと詳しいことを知りたいのであれば、 Github のリボジトリやWikiをみるとよさそうです。 Thor についてはまだ勉強中でまだよくわかりませんが、コマンドラインから実行するプログラムを作成するのを支援するようです。 継承関係は、 Rails::Generators::AppGenerator < Rails::Generators::AppBase < Rails::Generators::Base - [Thor::Actions, Rails::Generators::Actions] < Thor::Group - [Thor::Base, Thor::Shell, Thor::Invocation] となっていて、 < は継承しているところで - はミックスインしているところです。 Rails::AppBuilder には Rails::Generators::AppGenerator で使用するレシピが書いてある感じになっています。 Rails::Generators::AppGeneratorに定義されているメソッドは Thor::Group の規約により、定義された順番に実行されるようになっています。 --templateに指定したファイルが実行されるのは最後から二番目になります。 最後はrun_bundle が実行されます。これは bundle install が実行されます。 rails generator に対応したクラスのを多くは Rails::Generators::NamedBase を継承しています。 継承関係は Rails::Generators::NamedBase < Rails::Generators::Base となっているので、両者に共通するものが Rails::Generators::Base になることがわかりました。 rails new する時の処理をまるまる変更したいのであれば Rails::AppBuilder を継承して::AppBuilder を作成すればできそうな感じでした。 ベースになるクラスは railties/lib/rails/generators にあります。 generatorとして利用できるものは、ここに配置されているディレクトリに配置されています。 ないものもありますが、rails g --help に表示されるものと概ね対応しています。 find -maxdepth 2 -type d .

no_picture

Exception Notification の 4.x 系へのアップグレード

Rails のプラグインである Exception Notification を gem upgrade したらエラーが起きた。 例外が発生したらメールを送信してくれるやつです。 最近は Errbit とかが流行りらしいです。 ブルジョワ層は Airbrake とか使うらしいです。 話が剃れた。起きたエラーは以下の通り。 undefined method `new' for ExceptionNotifier:Module 対処方法は公式に書いてある。 Upgrading to 4.x version - Exception Notification ミドルウェアの名前が ExceptionNotification::Rack に変更された 第2引数に :email という上位にキーが必要になった production モードじゃないと発生しないので、Jenkins などで rake assets:precompile して置かないと発見が deploy するまで遅れそうです。

no_picture

Ruby on Rails で NOT IN な SQL をかく。

Rails 4 で NOT な条件をもつ WHERE 句 が非常に書きやすくなりました。 Rails 4 なら NOT IN な SQL も簡単に書けます。 User.where.not( name: ["hoge","goro"] ) 条件にリストを渡せばよいです。SQLは以下のようになります。 SELECT "users".* FROM "users" WHERE ("users"."name" NOT IN ('hoge', 'goro')) サブクエリも使えます。これが便利すぎて困る。 query = User.select(:name) User.where.not name: query SELECT "users".* FROM "users" WHERE ("users"."name" NOT IN (SELECT name FROM "users")) Rails 3 の話 そうはいっても、Rails 4 にすぐには更新できないプロジェクトがあるので、これに慣れてしまうと非常につらい。折角なのでメモしておく。 where に文字列を渡す 格好悪いけど、とりあえずごまかす場合はこれを使う。 User.where("name NOT IN ('hoge', 'goro')") 文字列で渡す。 ? を使うとエスケープで泣きたくなるので、手軽には使えない。右辺も文字列で逃げます。 サブクエリを使うときは、こんな感じ。 query = User.select(:name) User.where("name NOT IN (#{query.to_sql})") SQLを直接書くしかない。複雑な query だとつらいので to_sql メソッドで逃げます。 squeel を使う Rails 3 だと NOT なSQL を書きづらいので、 squeel をよく使っています。 squeel を使っていればこんな風に書けます。 User.where { name << ["hoge","mogu"] } where に ブロックで引数が渡せるようになって << という演算子を使うと NOT IN になります。name はシンボルではないのも ポイントです。 ブロックで渡すので、スコープ内で name に値が束縛されているとそちらを参照してしまうので注意。 サブクエリも使える。素晴らしい。 query = User.select(:name) User.where { name << query } squeel を使うと LIKE やら OUTER JOIN やらもできます。便利。 arel の世界へ行く arel で構築した sql を where に渡す方法がある。 squeel をインストールしたくない時に。 users = User.arel_table User.where( users[:name].not_in(['hoge','mogu']) ) arel 自体あまり解説してる人がいないのでなかなか勉強しにくいのが欠点。 わかってくるとなんとなくでも書けます。 サブクエリもいけます。 query = User.select(:name) users = User.arel_table User.where( users[:name].not_in(query.arel) ) ActiveRecord::Relation はそのまま渡せませんが arel メソッドで変換可能です。 まとめ Rails 4 の not 便利です。 squeel も良いです.

no_picture

rails4 で Asset の生成したいファイルの追加がうまいこといかなかった。

Rails4 を試していた。 1ページだけ全く違うデザインがあって js とか css を application.js とか application.css とは別に生成したかった。 ということで `config/environments/production.rb’ に config.assets.precompile += %w( hoge.js ) と書きました。 なぜか生成されない。Rails3 では間違いなく生成される。 調べてみたところ config/application.rb に書けば動くことがわかった。 それだけ。

no_picture

rails4 rc1 がリリースされたことだし beta1 からアップグレードしてみた

Rails 4.0 rc1 がリリースされてますね。軽いノリでアップグレードしてみたら余裕で起動しませんでした。 アップグレードするには Gemfile を以下の編集をしました。 -gem 'rails', '4.0.0.beta1' +gem 'rails', '4.0.0.rc1' gem 'pg' # Gems used only for assets and not required # in production environments by default. group :assets do - gem 'sass-rails', '~> 4.0.0.beta1' - gem 'coffee-rails', '~> 4.0.0.beta1' + gem 'sass-rails', '~> 4.0.0.rc1' + gem 'coffee-rails', '~> 4.0.0.rc1' あとは bundle update そんでもって起動すると下記のエラー。 gems/railties-4.0.0.rc1/lib/rails/application/configuration.rb:144:in `const_get': uninitialized consta nt ActionDispatch::Session::EncryptedCookieStore (NameError) CHANGELOG.mdには Automatically configure cookie-based sessions to be encrypted if secret_key_base is set, falling back to signed if only secret_token is set.

no_picture

Rails で外部キー制約

外部キー制約は好きですか? O/RマッパーしててもなるべくDBの力は借りたいです。 ということで、Ruby Toolboxで foreign を検索して、ちらちら見て一番人気のforeignerを選びました。基本的にはデータベースに丸投げなので Rails4 でもいまのとこ問題なく使えております。 インストールは Gemfile に: gem 'foreigner' と追加して bundle install あとはマイグレーションで: create_table :comments do |t| t.references :post, null: false, index: true t.foreign_key :posts, dependent: :delete end としておきました。 ついでに確認。 存在しない 外部キーを指定すると保存を失敗する確認。postgresの例: Comment.create(post_id: 1) # => PG::Error: ERROR: insert or update on table "comments" violates foreign key constraint "comments_post_id_fk" キーを指定して、親になるオブジェクトを削除すると消える確認: Comment.create(post_id: Post.create) Comment.count # => 1 Post.count # => 1 Post.first.destroy Post.count # => 0 Comment.count

no_picture

Rails で ajax をちょっと実験するときに `render text:` すると コールバックしてこない。

サンプルコードがなくて申し訳ないです。 rails で ajax を使用とすると 一般的には jquery-ujs を利用します。 あるリンクをクリックする時に非同期に読込みたい場合は <%= link_to 'hoge', @user, class: user-link %> に対して、 remote: true を追加します。 <%= link_to 'hoge', @user, remote: ture, class: user-link %> といった感じになります。 あとはサーバからのレスポンスが返ってきた時の処理を書きましょう。 $(function () { $(document).on('ajax:success', '.user-link', function (ujs, content, status, xhr) { $('#user-info').html(content); }); }); 少し説明不足ですが、気にせず。 さて、ここで リンク先が未実装で手抜きして: class UsersController def show render text: 'hoge' end end と、さくっと実装しちゃうと さきほど実装した javascript の コールバックが呼ばれません。 めんどくさがらずに、 app/views/users/show.htmle.rb などを作成してあげましょう。 そんなこと滅多にないか…。

no_picture

Rails4 beta1 がリリースされたのでアップグレードしてみた

Rails4 beta1がリリースされてます。 というわけで、アップグレードしてもよさそうなプロジェクトをアップグレードしてみました。(リリースしてないし) config以下の書き換えなどは自己責任で。 やったこと bundler 1.3 が必要になるので、まだいれていない場合アップデートします。 $ gem install bundler Gemfileを修正します。 gem 'rails', '4.0.0.beta1' group :assets do gem 'sass-rails', '~> 4.0.0.beta1' gem 'coffee-rails', '~> 4.0.0.beta1' # See https://github.com/sstephenson/execjs#readme for more supported runtimes # gem 'therubyracer', :platforms => :ruby gem 'uglifier', '>= 1.0.3' end 必要に応じてgemの設定 protected_attributes strong_parameters に移行してない場合 gem 'protected_attributes' devise devise がまだ対応 gem がないので gem 'devise', github: 'plataformatec/devise', branch: 'rails4' githubから直接。 simple_form gem 'simple_form', '3.0.0.beta1' simple_form が rails4

no_picture

今さらながら turbolinksを試した。- 感想

今さらながら Rails4 の新機能の一つである turbolinks を試してみました。 解説なんかは僕がするよりも様々な記事がもうあるので、あまり必要ないと思います。 Rails 4.0 に入る予定の turbolinks について調べた Rails4 Turbolinksのメモ #mtsmhack Rails4でデフォルトで入るturbolinksがオープンリダイレクタと合わさると何でもできてかなり危険 どれも良い記事でした。 ということで、個人的感想とか production環境より development環境での効果が高い気がした 体感ほんとに早い - development環境 だいたいそのままで動く。動かなくなる Javascriptはやっぱりある。 fancyboxとか、でも、そういうのはそもそもRailsで扱いずらいものばかり。 CSSやJavaScriptが切り変わるリンクには HTMLタグに data-no-turbolink属性をいれればよい。いれないと悲しいことになります。 インストール 一緒に jquery.turbolinks も入れておきました。 これは簡単に言うと、”なにもしなかったら動かなくなってしまうもの”を減らすように工夫したものだと思います。 なんとなくで具体的に書くと、readyイベントでやってることをページロードするときにも実行するようにするんじゃないかと思います。(たぶん) jquery.turbolinks は turbolinks に依存してないのでそれぞれGemfileに入れる必要がありました。 gem 'turbolinks` gem 'jquery-turbolinks' //= require turbolinks //= require jquery.turbolinks といった感じです。 感想をもうちょっと 体感ほんとに早い Rails3 でも試せるので、体感しておくのは良いと思います。設定はとても簡単なので、どういうものかは知っておいたほうが今後の方針に役立ちます。 個人的には、規模が大きいプロジェクトでは develpoment 環境でだけでも使いたいです。 動かなくなったプラグイン 試したプロジェクトは fancybox という jQueryプラグインが使用されてる箇所がありましたが、ここが動かなくなりました。 そもそも、Railsではこれはすごく扱いにくくて置き換えてやろうしてる部分で放置してるうちに次々と使われてしまってる問題児です。 修正するにはちょうどよい機会。 まとめ Rails的じゃないところほど問題がでやすい機能という点ですごく面白いなー。と、思いました。

no_picture

Cucumber の Capybara で 複数の同じ名前のリンクに対応するステップ

Cucumber のステップで もし /^"(.+)"をクリック$/ do |name| click_on name end というステップを書いていますが、name に複数マッチしてしまうとエラーが発生しています。同じ名前にならないようにすればいいのですが、そうもいかない場合もあります。結局、以下の方法を用意しました。 もし /^(\d+)番目の"(.*?)"をクリック_$/ do |n, name| n = n.to_i - 1 all(:link_or_button, name)[n].click end 何番目のリンクか指定することで回避しました。 もうちょっと詳しく click_buttonと同じことをやろうとすると find(name) や all(name) ではうまくいきません。調べてみると XPath::HTML.link_or_button というメソッドを使用して、findに渡すXPathを生成してることがわかりました。。 これをどうやって使うというと all の第一引数に使えばいいことがわかりました。 さらに詳しく page.class # => Capybara::Session click_onメソッドやallメソッドのレシーバである page オブジェクトは Capybara::Session でした。pry で調べました。 Capybara::Session NODE_METHODS = [ :all, :first, :attach_file, :text, :check, :choose, :click_link_or_button, :click_button, :click_link, :field_labeled, :fill_in, :find, :find_button, :find_by_id, :find_field, :find_link, :has_content?, :has_text?, :has_css?, :has_no_content?, :has_no_text?, :has_no_css?, :has_no_xpath?, :resolve, :has_xpath?, :select, :uncheck, :has_link?, :has_no_link?, :has_button?, :has_no_button?, :has_field?, :has_no_field?, :has_checked_field?, :has_unchecked_field?, :has_no_table?, :has_table?, :unselect, :has_select?, :has_no_select?, :has_selector?, :has_no_selector?, :click_on, :has_no_checked_field?, :has_no_unchecked_field?, :query, :assert_selector, :assert_no_selector NODE_METHODS.each do |method| define_method method do |*args, &block| @touched = true current_node.send(method, *args, &block) end end https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/session.rb#L338-L343 これらの メソッドは動的に生成されるようです。 def current_node scopes.last end def scopes @scopes ||= [document] end https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/session.rb#L351-L358 current_node は document という変数に格納されたオブジェクトのようです。 def document @document ||= Capybara::Node::Document.new(self, driver) end https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/session.rb#L334-L336 documentは Capybara::Node::Document クラスのインスタンスだとわかりました。 class Document < Base https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/node/document.rb#L11 ここには all メソッドがなく Capbyra::Node::Base を継承しているようです。 include Capybara::Node::Finders https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/node/base.rb#L27 この辺にありそうですね。 def click_link_or_button(locator) find(:link_or_button, locator).click end alias_method :click_on, :click_link_or_button https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/node/actions.rb#L12-L15 cloick_on みつけました。このあたりを grep でみつけた時点で all :link_or_button でいけそうなのはわかります。 def all(*args) query = Capybara::Query.new(*args) elements = synchronize do base.find(query.xpath).map do |node| Capybara::Node::Element.new(session, node, self, query) end end Capybara::Result.new(elements, query) end https://github.com/jnicklas/capybara/blob/2.0.2/lib/capybara/node/finders.rb#L110-L118 all みつけたー!

no_picture

ActiveRecord の has_many で生成されるメソッドってActiveRecord::Relationに変換できる配列なんですね。

タイトルのとおりなんですが、ArticleとComment とかあったりして、ちゃんと設定をしておくと article.comments とやると あるArticleに紐づいているCommentがとってこれる機能です。 まず、結論からいうと article.comments.to_sql とか article.comments.scoped とか article.comments.joinsとかできる!! ということです。 article.comments.create ってかける時点でうすうす思ってたんですが、これがわかっていると小回りがききます。返しているものが ActiveRecord::Relationのようなものです。classを確認すると Arrayって言われちゃいますが。 もうちょい深く 以下のクラスがあることを想定してみます。 class Article < ActiveRecord::Base has_many :comments end class Comment < ActiveRecord::Base belongs_to :artcile belongs_to :user end class User has_many :comment end さきほど紹介した技を紹介すると User.first かつ Article.first な Commentを探す場合、以下のように書けます a = Article.first u = User.first a.comments.merge(u.comments.scoped) すると、こんな SQLができます。 SELECT "comments".* FROM "comments" WHERE "comments"."article_id" = 1 AND "comments"."user_id" = 1 aとかuとかを引数な関数を用意するとウハウハな気がしてこないでしょうか。 joinだってできます。 a =

no_picture

Rails の rake notes というタスクをいまさらしった。

Rails Guide 読んでたら notes というタスクがあるのを知りました。 コードのコメントに TODO とか FIXME, OPTIMIZE といったコメントをみつけて表示してくれます。 grep すればいいやとか思いますが、それなりの便利そうです。jenkins なんかで回してレポートに出すのもよいかもしれません。 $ roke notes app/controllers/admin/users_controller.rb: * [ 20] [TODO] any other way to do this? * [132] [FIXME] high priority for next deploy app/model/school.rb: * [ 13] [OPTIMIZE] refactor this code to make it faster * [ 17] [FIXME] notes:custom というタスクもあるようです。 もう少しつっこんでみよう タスクのソースコードがここになります。 notes:custom では 環境変数 ANNOTATION で表示するキーワードを決められるようです。 notesの場合は “OPTIMIZE”, “FIXME”, “TODO” の3つか使用されていますね。 あと 動的にタスクを生成しているようなのでnotes:todo optimize fixme

no_picture

Devise で email 変更する。

Railsの plugin で 認証を行なう devise という gem があります。 このユーザ認証で 実際にユーザにメールを送信して、登録を完了するという機能を提供するのに confirmable という機能があります。 このConfirmableという機能を使用していると管理者が ユーザのメールアドレスを変更してあげる必要がある場合、代えるときもメールがユーザに送信されます。これが便利なときもあったりテスト時にこまったりすることがあります。 devise :confirmable した モデルには skip_confirmation! skip_reconfirmation! というメソッドが追加されてるので、これらを呼び出すことで回避することができます。 ちなみに、これらのメソッドの中身をみると def skip_confirmation! self.confirmed_at = Time.now.utc end def skip_reconfirmation! @bypass_postpone = true end となってます。 confirmed_at に値がはいっていれば有効で、@bypass_postpone が true で メールの送信が回避できそうですね。このあたりの実装はversionによって変更される恐れがあるので直接利用するには注意が必要です。

no_picture

ActiveRecordで関連レコードの自動保存

ActiveRecordで has_one なんかで関連づけしている場合、関連モデルを保存しわすれる。 そもそも、関連してることをドメインロジック上からは隠蔽したい。そんなときは autosave オプションが使えます。 関連するモデルが Information の場合、 has_one :information, autosave: true となります。 informationで親のモデル IDを validate presence かけてたらはまったことも一応メモしておきます。

no_picture

zeus test で スペックを実行すると 2度実行されてしまう

zeus test で spec を走らせるとなぜかスペックが2度実行されるようになっていた。 spec/spec_helper.rb 内の require 'rspec/autorun' を削除すると治るようです。 spork で実行してみたり、 rake spec したりもしてみたけど、消したから起きている問題は今のところないです。 追記 zeus rake spec したときに DB がリセットされてなくて上手く動いてないことがわかった。全件まわしたい場合は rake spec を使用してたので気がつかなかった。 参考 https://github.com/burke/zeus/issues/180

no_picture

read_attributeの存在を知らなかった、死にたい - rails

Railsの ActiveRecordで レコードの属性にアクセスする際は動的に生成されたメソッドを使いますが、そのようなメソッドを上書きしている場合、値に直接アクセスする必要があります。このような属性情報は @attributes に保存されています。 /lib/active_record/attribute_methods.rbに定義されてる attributes メソッドを経由してアクセスしていましたが、なんとなく @attributes へ直接アクセスするだけかとおもってたのですが、違ったようです。 def attributes attrs = {} attribute_names.each { |name| attrs[name] = read_attribute(name) } attrs end という定義になってました。 attribute_names は文字列で属性の一覧を返すので @attributesは 普通のHashでキーが文字列です。 もし email というの属性にアクセスしたい場合は attributes["email"] になります。 attributes[:email] ではアクセスすることができません。 しかし、 read_attributeは シンボルでも文字列でも使用することができて、 read_attribute :email でも read_attribute "email" のどちらでも良いみたいです。 ちなみにエイリアスがあって [] メソッドになります。なので self[:email] などでアクセスできます。pubilcメソッドです。 read_attribute があるということはも write_attribute もあります。 ついでにもう少し深追い read_attributeの実装もついでにおってみると def read_attribute(attr_name) self.class.type_cast_attribute(attr_name, @attributes, @attributes_cache) end となってました。クラスメソッドを経由するようです こいつも中身を追うと def type_cast_attribute(attr_name, attributes, cache = {}) #:nodoc: return unless attr_name attr_name = attr_name.to_s if generated_external_attribute_methods.method_defined?(attr_name) if attributes.has_key?(attr_name) || attr_name == 'id' generated_external_attribute_methods.send(attr_name, attributes[attr_name], attributes, cache, attr_name) end elsif !attribute_methods_generated?

no_picture

ViewSourceMap が地味に役に立つ

ViewSourceMapというのが地味に役に立ちそうなので導入してみた。 部分テンプレートを render して出力された前後にどの view をレンダーしたのかHTMLのコメントを挿入してくれる。 <!-- BEGIN app/views/users/_form.html.haml --> <form /> <!-- END app/views/users/_form.html.haml --> ついでに、partial以外のレイアウトとかメインのビューとかもついでに出力してみるのもありかなと思ったりもするけど、その辺は明確だし、時間ができたら fork してみよう ソースコードも短いしRails の plugin 的なものを作ってみたいときにも参考になりそうでした。 https://github.com/r7kamura/view_source_map

no_picture

ruby 2.0.0-preview2 をいれて rails起動してみた

ruby 2.0.0-preview2 が出てるのでビルドして rails を起動してみた。 $ uname -v Darwin Kernel Version 12.2.1: Thu Oct 18 16:32:48 PDT 2012; root:xnu-2050.20.9~2/RELEASE_X86_64 preview1のときと同様にopenSSLがついてこないので、OpenSSLを一緒にビルドするようにrbenvを修正しました。[https://github.com/eiel/ruby-build/tree/2.0.0-preview2-with_openssl] bundle instalの実行で ~/.rbenv/versions/2.0.0-preview2/lib/ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require’: cannot load such file – rubygems/format (LoadError) と出てしまいますが rubygemsのライブラリ構成が変わっててbundlerが動かないだけみたいなので、 $ gem install bundler --version ">= 1.3.0.pre2" として 1.3 系の gem をいれました。 あとは普通に rails が起動できました。

no_picture

TagHelperっていうのがあるんだけど、周りの人が使ってない - Rails

Railsのhelperに TagHelper っていうのが text_area_tag のようなフォームを作成するような Helper がありますが、その内部で使用するようなメソッドが定義されています。 主に tag, content_tag になるのですが、自分でHTMLのタグを生成するようなヘルパーを生成したときこれを使うと便利です。 例えば hoge的なものを表現するタグを生成するhoge_tagという抽象化をしたいときにざっくりな実装をすると以下のようになります。 def hoge_tag(content) %Q{<div class="hoge">#{content}</div>}.html_safe end hoge_tag "hogehoge" # => "<div class=\"hoge goro\">hogehoge</div>" しかし、つかっていくと個別に class属性を追加したくなる場合が多々ありますし、content の escape などもしないといけないです。 def hoge_tag(content, *classes) classes = ["hoge"] + classes class_string = classes.join(" ") %Q{<div class="#{class_string}">#{content}</div>}.html_safe end hoge_tag "hogehoge", "goro" # => "<div class=\"hoge goro\">hogehoge</div>" もちろん、class属性だけじゃなくていろいろ指定したくなります。 text_area_tag なんかと同じようにoptionsで受けるようにしたい。こうなっとときに 「ソースを読もう!!」 という発想が出るようになると良いと思います。 def hoge_tag(content, options = nil) classes = options[:class] classes = [classes] unless

no_picture

ActiveSupport::Concern - Railsのソースとか読みはじめた 2

ActiveSupport::Concern - Railsのソースとか読みはじめたの続きになるのですが、 @netwillnet さんに。 ActiveSupport::Concernはモジュールが少しだけ書きやすくなるというメリットよりも、複数のモジュール同士に依存関係があったときにモジュール内でその依存関係をうまく解消させられるところに真価があるのでは https://twitter.com/netwillnet/status/270150759335723008 と素敵な突っ込みを頂いたので、rdocとソースコードと睨めっこしてきました。 睨めっこした結果の結論を書きたいと思います。 というわけで A -> B -> C という依存性があるモジュールを考えます。A には B が必要で。 B には C が必要という意味です。 module C def c "c" end end module B include C def b "b" + c end end class A include B def a "a" + b end end A.new.a と実行すると "abc" と出力されます。 これと同じことをクラスメソッドで実現しようとしてみます。 module C2 def c "c" end end module B2 def b "b" +

no_picture

Rails 3.2.9 で default_scopeに設定してる条件が属性の初期値になるらしい

あるプロジェクトでrails 3.2.9 にアップデートしたら テストが失敗しまくる。そのひとつに ActiveRecordの default_scope を使ってる部分に問題があるとわかった。 どんなエラーかと言いますと。 NoMethodError: undefined method `to_i' for [1, 2, 3]:Array from activerecord-3.2.9/lib/active_record/connection_adapters/column.rb:178:in `value_to_integer' [1, 2, 3] とか即値すぎて わけがわからないよ という感じだったんですが、いろいろ調べると class User < ActiveRecord::Base default_scope proc { where(state_id: [1, 2, 3]]) } end というコードがあったときに User.new すると発生することがわかりました。 仕方ないので、 class User < ActiveRecord::Base scope :valid, proc { where(state_id: [1, 2, 3]]) } end として、ひたすら置換しまくりでした。 僕はdefault_scope使わない派なのであまり気にしない方向で。 ちなみに class User < ActiveRecord::Base default_scope proc { where(state_id: 1,name: "hoge") }

no_picture

ActiveSupport::Concern - Railsのソースとか読みはじめた

Railsのソースをちょろちょろ読むようにしている。読んで学んだことをメモしておきたい。だいたい読んだ当時の最新リリースを参考にします。 ActiveSupport::Concern を読みました。 このモジュールはモジュールの定義を手助けします。 クラスメソッドの定義場所をルール決めして include するだけで済むようにしたり、クラスのコンテキストで実行したい処理を書く場所を用意してくれます。 具体的にいきます。 以下のコードがあったとします。 class ConcernSample attr_accessor :hoge def self.mogu "mogu" end def goro "goro" end end これを以下のようにするだけで同じ機能を提供できるようにしたいと思います。 class ConcernSample include Sample end 処理を Sample モジュールにまとめたいということです。 これができると class ConcernSample include Sample end class ConcernSample2 include Sample end class ConcernSample3 include Sample end と、似たような機能をもつクラスを量産できます。 クラスに機能を追加するのが簡単になるという視点を持つとよいでしょう。 さて、Sample はどのように書くかということです。 ここで ActiveSupport::Concern を利用します。 require 'active_support' module Sample extend ActiveSupport::Concern included do attr_accessor :hoge end module ClassMethods def mogu "mogu"

no_picture

cucumber で表示した画面がXMLを出力しているか確認する

rspec でマッチャーがあればよいのですが、とりあえず心当たりがなかったので、適当にごまかしました。良いgemがあれば紹介して欲しいです。 page.source が サーバからの出力を返してくださるので、これを Nokogiri で parse させてエラーがないかどうかで確認しました。 ならば /XMLを出力する/ do errros = Nokogiri::XML(page.source).errors expect(errors).to be_empty end どうせなら下記のように書きたいですね。 ならば /XMLを出力する/ do should render_xml end マッチャーを書いてみます。 RSpec::Matchers.define :render_xml do match do |actual| Nokogiri::XML(actual.source).errors.empty? end end ほとんどそのままです。matcher つくるのは難しくないので気軽に作りたいです。 少しだけ解説。 y cucumberの中では subject を省略した場合は page になります。なので、 ならば /XMLを出力する/ do page.should render_xml end と書いたのと等しいです。なので、acutual には page オブジェクトがバインドされていますので、そこから source を取り出してチェックします。page オブジェクトには html というメソッドが存在しますが、ブラウザが解釈したあとのDOMをdumpしたような感じになってるので期待通りの動きをしませんでした。

no_picture

Railsによる開発にはzeusが新たな定番になりそう。

rails c や rake spec ってすごく時間がかかる。それをできるだけ早くするプロダクトはいままでにもいろいろありました。rails-shとかsporkとか。 そんな中zeusというのが最近登場したみたいです。gem install zeusu でインストール。Gemfileに書いてもいいそうですが、かかなくて良いようです。 あとは RAILS_ROOTで zeus init して zeus start しておけば、あとは別の端末で zeus c や zeusu sとして使うだけです。ファイルを変更すると認識して再読込します。zeus initした際にzeus.jsonが生成されます。 変更箇所に応じて必要なところからforkしなおすような挙動をしているように見えます(よくわかっていません) cucumberやrspecも認識して zeusu cucumber や zeusu spec というものも用意してくれます。 まだ使い込んでいませんが、イノベーションを感じるのでしばらく使ってみようと思います。

no_picture

database.ymlが.gitignoreに入っている環境でのcapistranoを使ったデプロイ

[2012-09-20日追記] 以下の記事の内容ですが、gemが用意されてました。 https://github.com/amfranz/capistrano_database_yml Railsプロジェクトで、ひとりで開発している場合は除いて、.gitignoreにconfig/database.ymlを追加することがよくよくあります。この場合、config/database.ymlをどこかのタイミングで作ってやらなければなりません。この対処法はこの記事で説明されてます。 概略 英語だったりするので簡単に説明をかいておきます。 前述の記事の作業を行うとcapコマンドにふたつのタスクが追加されます。 cap db:setup cap db:symlink db:setupはshared_pathにconfig/database.ymlに生成してくれます。すでにあると上書きされるので注意が必要です。 db:symlinkは db:setupで生成したconfig/database.ymlへsymlinkを貼ります。なので、#{shared_path}/config/database.yml手で編集しておけば良いということになります。 試したときに困ったことなど 記載されているコードをコピーして、capistrano_database.rbを作成するのですが、このファイルをどこに作成すべきなのか記述されていないので、lib上に作成しました。 libはLOAD_PATHが通ってないのに気付かなくて迷惑をかけました。 config/deploy.rbに require "capistrano_database"とするところをrequire "./lib/capistrano_database"として回避しました。 ところが、cucumberの実行時のオプションに--require libをつけているせいだと思いますが、cucumberの実行時に読み込まれてしまい不具合がでてしまったので、 Capistrano::Configuration.instance.load do .... end の部分を if instance = Capistrano::Configuration.instance instance.load do ... end end のように変更して回避しました。

no_picture

Railsでコントローラのスペックを試行錯誤中

Rspec書いてますか?最近なかなか荒れ気味ですが、僕はなんだかんだで嫌いじゃないです。 コントローラのテストは何をすべきかなかなか難しいです。 こんな感じでどうかなーというのを一応紹介しておきます。 何をテストするか 基本的には rspec を走られせるとこのコントローラが何をするのかわかるようにすることです。 どのアクションがどのHTTPメソッドを受けるのか どんな変数をビューに渡すのか リダイレクトするのか、しないのか どんなflashが設定されるのか 前提とする状況はなにか といったあたりがわかるようにしています。 どのアクションがどのHTTPメソッドを受けるのか これは単純にdescribeにかくだけですが、コード上ではlet式を利用して request という変数にバインドしてちょっとだけ目立つようにしています。 どんな変数をビューに渡すのか ビューに渡す値はインスタンス変数に入れますが、どの変数にどんな型の値が入るのかテストしています。 ビューを先にかくことが多いのでその際にpendingにして追加していくとコントローラかくときにビューの確認をする必要がありません。 あと、before_filterのようなものを利用しているの、その中で勝手にバインドするものがあるのでこれを明確にしてやったりします。 リダイレクトするのか、しないのか 対応するビューがあるのかないのか、うまくいくのどこの画面にいくのかが明確になるのでかいておきます。 どんなflashが設定されるのか これは変数の場合とだいたい一緒です。ビューではなく cucumber でのテストとの橋渡しな感じもあります。私はcucumberでは成功したらこの値が出てるのか確認してます。 前提とする状況はなにか ログインしている場合なのか、とかです。contextのブロックが増えるだけです。 それらを踏まえて上での雛形 コメントは解説のために。 describe HogeController do subject { request } describe "GET 'index'" do let(:request) { get :index, params } let(:params) { { hoge: "mogumogu"} } context "ログインしている時" do include_context "ログイン" # リダイレクトなどしない場合 it { should be_success } context "リクエストした時" do #

no_picture

ActiveRecordで今のスコープをそのまま返したい

あるオプションパラメータがあるかどうかで、条件が変わるような処理を書いてると、オプションがない場合、ActiveRecord::Relationが欲しくなるような場面があります。 例えば @articles = Article @articles = @articles.where(valid: true) if params[:valid] みたいな感じになっちゃって@articles = Articleって何?な状態になります。 メソッド化しようとするとさらに困るのですが、scopedを使うと以下のように書けるようです。 @articels = Article.scoped @articles = @articles.where(valid: true) if params[:valid] なんか異臭がしなくなりましたね。 だから、どうした?って思う方もいるかもしれませんがメソッド化すると、 def self.valid(is_valid = nil) scoped.where(valid: true) if is_valid scoped end となります。scopedなしで書かこうとするとちょっと困ります。 そんだけ。

no_picture

Ruyb on Railsにて render を before_filterとかafter_filterで読んだら酷い目にあった

コントローラ内デいろんなところで同じrenderを書いてたのでリファクタリングしようと思った。 そんなわけで after_filter を利用して render を呼んでみましたが、actionの処理がすでに終了してるようで、 renderは一度呼んでるよ! って怒られました。 仕方なく before_filter で呼んだら、action内に入る前にレンダリングしてしまって、@hogehoge がnilやねーんって怒らました。 とりあえず、あきらめることにしました。

no_picture

Rspecマッチャー rspec-html-matchersを試してみてる

Ruby on Railsで ViewやHelperの Specを書く際に利用するマッチャーに良いのがないか探してます。現在のRspecはcontainぐらいしかないので、細かくチェックしたい場合は若干使いづらいです。というわけで、rspec-html-matchersを試しています。 以前は rspec-tag_matchers を使用していたのですが、出力がちょっとイマイチでした。 Ruby Toolsでざらざらと探した結果、rspec-html-matchersを試してみることにしました。 Form用のマッチャーがいろいろあったり、内部に存在するタグをチェックしたりできるのが嬉しいですね。capybaraのhave_cssはsubject側で find(selector)しておく必要があるので、ややめんどくさいです。 いまのところの不満点は Hashで渡していくのがちょっと格好悪い 正規表現での属性チェックができなかった 暗黙的なsubjectを使用する場合、ブロックがあると不具合がでる 3番目なんですが、have_tag マッチャーにブロックを渡し場合 shouldメソッドのレシーバをかかないと、ブロック内へと処理が流れないようです。 subject { render } it do should have_tag("a") do # このブロック処理が走らない with_tag("b") end end のように書いてしまうと with_tag("b") の部分が動作しません。3行目を明示的に subject.shouldとすると動いてくれました。rspecの問題なのか、rspec-html-matchersの問題なのか切りわけが難しいのでとりあえず、我慢することにしました。 ブロックを渡さない場合は大丈夫です。 他は良好に使えています。 View Specの良い例が欲しいです。