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

RailsによるアジャイルWebアプリケーション開発を読む

興味と必要にかられてRubyとRoRを勉強し始めたので、そのメモです。

まず「たのしいRuby」を買いました。そして3時間ぐらいでざっと読み終え*1、早速Railsを触ってみることにしました。とりあえず、鉄板の「RailsによるアジャイルWebアプリケーション開発(第4版)」を借りたので、現在写経しているところです。

プログラミングHaskellの時のように一章ごとにレビューを書くようなことはしませんが*2、読み進め次第、特に詰まったところを中心に、どんどん追記しようと考えてます。

環境情報

  • Mac OS X Mountain Lion (10.8)
  • ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.4.0]
  • Rails 3.2.3

メモ

第9章

ここまで、基本的に間違えずに写経すれば、ちゃんと動作するのですが、この章では色々$ rake test:functionals時にエラーが出てしまいました。

まず、

/usr/local/Cellar/ruby/1.9.3-p194/lib/ruby/gems/1.9.1/gems/activerecord-3.2.3/lib/active_record/relation.rb:378:in `destroy': wrong number of arguments (0 for 1) (ArgumentError)

というエラーが出ました。これには、
Pragmatic Forums | Error: 'destroy' wrong number of arguments
のBen氏の投稿が参考になりました。結局、自分のタイポが原因で、cart.rbのdestroyをシンボルにすることで無事解決しました。

# イテレーションD2を参照
..
  has_many :line_items, dependent: :destroy # ←

これが解決した後に、2つ目の問題が発生しました。

  1) Error:
test_should_create_line_item(LineItemsControllerTest):
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: product

先の問題はコーディングミスでテストのエラーではありませんが、こちらはテストの問題です。とりあえず、検索した所
http://forums.pragprog.com/forums/148/topics/10565
が見つかりました。このトピックには幾つかの対処法が載っているのですが、とりあえず私の環境ではTerry氏の方法で解決できました。

LineItemsController#create内のbuildの部分を

    @line_item = @cart.line_items.build(product_id: product.id)

と修正しました。何でこれで解決したのか全く見当がつかないレベルなので、とりあえず保留します。いつか追記するかもしれません。

第10章

ここではまずquantityレコードを追加して、さらにDBを操作して今の複数同じproduct_idの列がある状態をなんとかしようというお話のようです。で、combine_items_in_cartというマイグレーションを作成してupメソッドを実装後、rake db:migrateするのですが、以下のように失敗してしまいました。

==  CombineItemsInCart: migrating =============================================
rake aborted!
An error has occurred, this and all later migrations canceled:

Can't mass-assign protected attributes: quantity

前章でもそうだったので段々分かって来ましたが、mass-assign attributesなエラーメッセージは、アクセス権限がないために出るエラーのようです。そこで、LineItemモデルを以下のように修正しました。

class LineItem < ActiveRecord::Base
  attr_accessible :cart_id, :product_id, :quantity # ←
  belongs_to :product
  belongs_to :cart
end

とりあえず、これで問題無さそうです。このあとすぐdownを実装しておくことでいつでもrollback出来るようにしようというのは良い心がけですね。

*1:クラスやモジュールの理解が甘いですが、実践で学ぶってことで

*2:あれも9章で止まっているので暇ができたら読まねば…暇出来るの数カ月後になりそうだけど。