#318 Upgrading to Rails 3.2 - RailsCastsを見て
手持ちのRails3.1アプリをRails3.2.2へupgradeしてみました。
あと、後半は新機能のお試しです。
すでにRails 3.2.2がリリースされています。
3.1系から一気に3.2.2へupgradeも可能です。
upgrade作業自体は、3.1の時のような面倒さは無く
いわいる普通のupgrade作業でした。
準備
0.Rails3.1へ
Rails2系の人はひとまず
Rails3.1.0へのupgrade方法 - うんたらかんたら日記こちらへ
1.Rails3.1(3.1.4)の最新へ
1)Gemfile内のrailsのversionをあげる
2)bundle update rails
3)bundle exec rake rails:update
4)差分を確認しながら必要な箇所は更新 bundle exec rake db:migrate
5)テストが通ることを確認 bundle exec rake spec
2)実行時に下記エラーとなりました。
rack versionがあがっているようなので、エラーメッセージのようにして、再度実施。
(※あとで動画見直したら、Gemfile内にrackの指定がなかったので、多分rackの行は削除でOK)
Bundler could not find compatible versions for gem "rack": In Gemfile: rails (= 3.1.4) ruby depends on rack (~> 1.3.6) ruby rack (1.3.3)
upgrade
2.ブランチをきる
まずは作業用ブランチを切ります。
git checkout -b rails32
3.Gemfile修正
1)Gemfile内のrails他のversionをあげる
私は3.2.0にupgrade後3.2.2へ再びupgradeしましたが、
設定ファイルの変更点は無かったので、直3.2.2へupgradeでも問題ないでしょう。
gem 'rails', '3.2.0' group :assets do gem 'sass-rails', " ~> 3.2.3" gem 'coffee-rails', "~> 3.2.1" gem 'uglifier', '>= 1.0.3' end
2)bundle update
2)実行時に下記エラーとなりました。
rack versionがあがっているようなので、エラーメッセージのようにして、再度実施。
(※あとで動画見直したら、Gemfile内にrackの指定がなかったので、多分rackの行は削除でOK)
Bundler could not find compatible versions for gem "rack": In Gemfile: rails (= 3.2.0) ruby depends on rack (~> 1.4.0) ruby rack (1.3.6)
各種設定ファイルを修正
railscastsではコピペしてますが、
rake rails:update での差分と同じなので
各自で確認しながら必要な箇所を更新していくと
追加機能の設定個所が分かっておすすめです。
4.development.rb
追加。
# Raise exception on mass assignment protection for Active Record models config.active_record.mass_assignment_sanitizer = :strict # Log the query plan for queries taking more than this (works # with SQLite, MySQL, and PostgreSQL) config.active_record.auto_explain_threshold_in_seconds = 0.5
5.production.rb
ここは変更は無いのですが、下記のようにコメントが追加されています。
log_tagsと、loggerのclass変更、auto_explain_threshold_in_secondsが
利用できるようになっています(後述)。
+ # Prepend all log lines with the following tags + # config.log_tags = [ :subdomain, :uuid ] + # Use a different logger for distributed setups - # config.logger = SyslogLogger.new + # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new) + # Log the query plan for queries taking more than this (works + # with SQLite, MySQL, and PostgreSQL) + # config.active_record.auto_explain_threshold_in_seconds = 0.5
6.test.rb
追加。
# Raise exception on mass assignment protection for Active Record models config.active_record.mass_assignment_sanitizer = :strict
削除。
# Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets config.assets.allow_debugging = true
その他
こんなのも追加されてます。
config/initializers/inflections.rb
+ # + # These inflection rules are supported but not enabled by default: + # ActiveSupport::Inflector.inflections do |inflect| + # inflect.acronym 'RESTful' + # end
7.テストが通ることを確認 bundle exec rake spec
あとは、masterにmerge。
以上。
新機能について
ほぼascii castと同じです。
自分なりに試した内容を記載しています。
mass_assignment_sanitizer
development.rbに追加された機能設定です。
mass assingment対策(attr_protected)している際、
更新対象カラムに含まれていた場合、例外が発生します。
試してみると下記のような例外が発生しました。
いい機能ですね。
ActiveModel::MassAssignmentSecurity::Error in UsersController#update Can't mass-assign protected attributes: admin
auto_explain_threshold_in_seconds
これも素晴らしい。遅いクエリに対してexplainを実行してログに出力。
explain
putsがおすすめ。
>> puts User.order(:name).explain User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY name EXPLAIN (0.1ms) EXPLAIN QUERY PLAN SELECT "users".* FROM "users" ORDER BY name EXPLAIN for: SELECT "users".* FROM "users" ORDER BY name 0|0|0|SCAN TABLE users (~1000000 r
pluck
User.select(:name).map(&:name)と結果は同等です。
>> User.pluck(:name) (0.3ms) SELECT name FROM "users" => ["foo", "bar"]
uniq
重複排除。
first_or_create / first_or_create!
これも名前の通り。
safe_constantize
これはリリースノートから見落としていました。
constanize(こいつも知りませんでしたが)の例外発生させないverのようです。
>> "User".safe_constantize => User(id: integer, name: string, admin: integer, created_at: datetime, updated_at: datetime) >> "User".constantize => User(id: integer, name: string, admin: integer, created_at: datetime, updated_at: datetime)
>> "Usera".safe_constantize => nil "Usera".constantize NameError: uninitialized constant Usera
migration
リリースノート見て理解できてませんでしたが
:index 指定が追加されています。あと小数点の設定も可、型のデフォルトはstring。
$ rails g model product_variation product_id:integer:index name 'price:decimal{7,2}'
.railsrc
今のところ使う予定は無いですが、
下記のようにしておくとrailsコマンド時にoption設定が自動で読まれるようです。
$ echo -d postgresql -T > ~/.railsrc
ActiveRecord KVS
いまいち理解していませんでしたが、面白い機能追加です。
ActiveRecord上に専用のカラムを追加して、下記のように定義すると
kvsチックに利用できます。
たまに、「運用時にデータ構成が変化したりするデータをhash形式で放り込んで自前でパースして」
みたいなことをやったりしますが、パースをActiveRecordで勝手にやってくれるので便利そうです。
当然ながら検索条件としては利用できません。
#model class User < ActiveRecord::Base attr_protected :admin store :properties, accessors: [:colour, :size] end
# migration $ rails g migration add_properties_to_user properties:text $ rake db:migrate
# rails console >> u = User.new(colour: 'blue', size: 3) => #<User id: nil, name: nil, admin: 0, created_at: nil, updated_at: nil, properties: {:colour=>"blue", :size=>3}> >> u.colour => "blue" >> u.properties => {:colour=>"blue", :size=>3} >> u.properties[:colour] => "blue"
# db sqlite> select '/' || properties || '/' from users where id = 4; /--- :colour: blue :size: 3 /
hash形式で入ってますね。
log_tags
config.log_tags = [ :uuid, :remote_ip, :port ]
これもいいですね。
ActiveSupport::TaggedLoggingの機能で[]を付けて表示しているっぽい。
Started GET "/users" for 127.0.0.1 at 2012-03-04 20:08:49 +0900 [9fa15030ac1b5e96e035fd8ebc2305bc] [127.0.0.1] [3000] Processing by UsersController#index as HTML [9fa15030ac1b5e96e035fd8ebc2305bc] [127.0.0.1] [3000] User Load (0.3ms) SELECT "users".* FROM "users" [9fa15030ac1b5e96e035fd8ebc2305bc] [127.0.0.1] [3000] Rendered users/index.html.erb within layouts/application (16.3ms) [9fa15030ac1b5e96e035fd8ebc2305bc] [127.0.0.1] [3000] Completed 200 OK in 107ms (Views: 97.8ms | ActiveRecord: 0.3ms) [6816ed840b5a98fcb1c8042567c1df51] [127.0.0.1] [3000]