2011年5月22日日曜日

rails自体の開発環境を作る3

■概要

rails3をモジュール別にテストしていますが、activerecordだけはDBの準備があるので少し面倒そうです。

■activerecord

○sqlite3

$ cd activerecord
$ RUBYOPT=-W0 rake test_sqlite3

......
2986 tests, 9101 assertions, 0 failures, 0 errors, 2 skips

とくに問題なさそうだ。

○mysql & postgresql

まずはデータベースの準備

# yum install mysql mysql-devel mysql-server
# yum install postgresql84 postgresql84-contrib postgresql84-devel postgresql84-libs postgresql84-server

bundlerが、"DB無し設定"なので、再取得する。

$ rm .bundle/config
$ bundle install (adapterのコンパイルが成功するはず)

mysqlの下準備は、ユーザの権限付与とDB構築

# /etc/init.d/mysqld start
$ mysql -u root
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
mysql> GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
$ cd activerecord
$ rake mysql:build_databases

postgresqlの下準備は、DB作成とユーザ周り

# service postgresql initdb
# /etc/init.d/postgresql start
$ sudo -u postgres createuser --superuser $USER
$ cd activerecord
$ rake postgresql:build_databases

で、テストを実行

$ RUBYOPT=-W0 rake test
......
2977 tests, 9114 assertions, 0 failures, 0 errors, 2 skips

お、動いた!!(postgresqlで2つ程落ちてますが。。)

■次回予告

ここまでの作業を纏めて、目指せコントリビュータ!な感じにしようと思います。

2011年5月21日土曜日

論理データベース設計(ER図)のチェックリスト

■概要

職業がら、顧客と会話しデータベースの論理設計をする事が良くあります。
自分で設計する分には良いんですが、他人が設計した物を効率的にチェックする為に備忘録がてら記載しておきます。

ちなみに当方は「渡辺幸三さんの著作」と「アナリシスパターン」の影響を一番受けています。

■チェック項目
○キーについて
・データの一意性が、利用者(顧客)と意識があっているか
・PKの無いテーブルはないか
・UKが明示されているか
・多すぎる複合キーはないか
・自然キーとサロゲートキーを意識できているか
・ID / コード・番号を使い分けているか
・FKを意識できているか
・FK/区分との使い分けは考えられているか
・属性項目のドメインを規定する物なので使い分けの基準が重要

○属性について
・ドメイン管理を意識して属性名を付けているか
・継承項目、導出項目が明示されているか
・継承・導出ルールが明示・意識されているか
・時点記録を意識して導出項目を設計しているか?

○多重度・関係について
・多重度が間違っていないか
・1-1関連が存在しないか
・"0以上"なのか"1以上"なのか考察できているか
・親子と参照を意識して使っているか
・派生関係を意識できているか

○正規化について
・繰り返し項目が除去できているか(もしくは意識できているか?)
・PKからの関数従属性のみになっているか
・キー組み合わせについてデータが表現出来ているか

○その他について
・インスタンスレベルでイメージできているか
・インスタンスにするべき概念がテーブルになってないか
・パラレルに重複した構造・関係はないか
・プログラムとの連携を意識できているか
・知識・操作レベルを意識できているか
・データのライフサイクルを意識できているか
・区分が設計されているか
・状態の管理が意識できているか
・人間はミスをするという事を意識できているか
・業務にキャンセルがありえる事を意識できているか

■雑感

思いつくまま記載しても結構あるな。思い出したら追加していこう。。

2011年5月18日水曜日

rails自体の開発環境を作る2

■概要

前回とりあえず環境が出来たのでモジュール毎にtestcaseを実行していきます。

■actionmailer

$ cd actionmailer
$ RUBYOPT=-W0 rake test
......
Finished in 7.010759 seconds.

181 tests, 487 assertions, 0 failures, 0 errors, 0 skips

全部OKだ!

■actionpack

$ cd ../actionpack
$ RUBYOPT=-W0 rake test
......
Skipping MemCacheStoreTest tests. Start memcached and try again.

どうもmemcachedが必要そうです。

# yum install libevent libevent-devel
# cd /usr/local/src
# wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
# tar xvfz memcached-1.4.5.tar.gz
# cd memcached-1.4.5
# ./configure
# make
# make install
# cp /usr/local/src/memcached-1.4.5/scripts/memcached.sysv /etc/init.d/memcached
# vim /etc/init.d/memcached
(memcachedコマンドが見つからないと言われるので、/usr/local/bin/memcachedとした)
# /etc/init.d/memcached start

で再度挑戦

$ RUBYOPT=-W0 rake test
...F......F...
Finished in 68.901053 seconds.

1) Failure:
test_default_params(TestRoutingMapper) [test/dispatch/routing_test.rb:1448]:
<"home"> expected but was
.

2) Failure:
test_non_greedy_regexp(TestRoutingMapper) [test/dispatch/routing_test.rb:1791]:
expected but was
.

3117 tests, 14823 assertions, 2 failures, 0 errors, 0 skips
二つほど落ちているが、一旦無視する。

2011/05/22追記 => 今日見たら全部OKでした。

■activemodel

$ cd ../activemodel
$ RUBYOPT=-W0 rake test
......
Finished in 1.524920 seconds.

492 tests, 1323 assertions, 0 failures, 0 errors, 0 skips

全部OKだ!

■activeresource

$ cd ../activeresource
$ RUBYOPT=-W0 rake test
......
Finished in 3.307448 seconds.

284 tests, 877 assertions, 0 failures, 0 errors, 0 skips

※いくつかDEPRECATIONが出ていました。

2011/05/22追記 => 今日見たら出てませんでした。

■activesupport

$ cd ../activesupport
$ RUBYOPT=-W0 rake test
......
Finished in 7.790476 seconds.

2477 tests, 10526 assertions, 0 failures, 0 errors, 0 skips

全部OKだ!

■railties

$ cd ../railties/
$ RUBYOPT=-W0 rake test
......

すごく時間がかかりますが...3つ程落ちました。。

■activerecord

...次回に続く...

2011年5月17日火曜日

rails自体の開発環境を作る1

■概要

そういえばrails自体の開発環境を作成したい場合どうしたら良いのか?
http://guides.rubyonrails.org/contributing_to_ruby_on_rails.htmlを参考にcentos5.xに環境を作成してみる。

■環境確認&準備

バージョン確認
$ ruby -v
ruby 1.9.2p180 (2011-02-18 revision 30909) [x86_64-linux]

必要なプロダクト等インストール
$ sudo yum install libxml2 libxml2-devel libxslt-devel
$ sudo yum install sqlite sqlite-devel
$ sudo gem install bundler

■railsを取得&テスト実行

$ git clone git://github.com/rails/rails.git
$ cd rails
$ bundle install --without db
$ rake test (全体をテスト。但しmysql/mysql2/postgresql依存は落ちます)

なおモジュール単位でのテストの実行は(例 actionpack)

$ cd actionpack
$ rake test

で良いようです。ちなみにwarningが発生しているので

$ RUBYOPT=-W0 rake test

とすればwarningを抑えられます。続く...

■雑感

う~む、意外にwarningが結構多発しているんですね(AM以外は何かしら発生します)。
後memcached用意した方が良さそうですね。。

2011年5月7日土曜日

rails 3.1 RC4の変更点を翻訳してみた

こちらで公開されているrails3.1 beta1の変更点を翻訳してみました。

(更新)2011/07/20 rails3.1 RC4にしました。

作業途中&超適当翻訳ですが、無いよりはましだと思うので公開します。
埋め込み方がいまいち良くわからないので、こちらへどうぞ。
(凹まない程度の)ツッコミ募集中です!

# どなたか綺麗に埋め込む方法教えてください。↓実験中。

Railties 3.1 RC4

  • 新しいrakeタスク assets:clean はプリコンパイルされたアセットを削除する。

  • --skip-gemfile--skip-bundleなしでの、アプリケーションとプラグインのソース生成は、bundle installを走らせる

  • jdbc*アダプターにとってのデータベースタスクを修正した

  • jdbcpostgresqlにとってのテンプレート生成

  • jdbcmysqlとjdbcsqlite3にとってのテンプレート生成

  • アプリケーションジェネレータの -j オプションは任意の文字列を受け付ける。"foo" が渡されれば、Gemfileに "foo-rails" gemが追加され、アプリケーションのJavaScriptマニフェストは、"foo" と "foo_ujs" を要求する。現在 "prototype-rails" と "jquery-rails" があり、assetパイプラインを経てファイルは提供される。デフォルトは"jquery"。

  • jQueryは、もはやvendoredではなくjquery-rails(gem)によって提供される。

  • PrototypeとScriptaculousは、もはやvendoredではなくprototype-rails(gem)によって提供される。

  • もしSassが利用出来るなら、scaffoldコントローラはSCSSファイルを生成するだろう。

  • コントローラとリソースジェネレータは、自動的にassetスタブを生成するだろう(--skip-assetsでオフにできる)。(もし利用出来るなら)スタブはCoffeeとSassを利用する。

  • jQueryが新しいデフォルトのJavaScriptライブラリ。

  • scaffoldとappジェネレータはRuby1.9においては、Ruby1.9スタイルのハッシュで生成する。

例えば次のような場合:

redirect_to users_path, :notice => "User has been created"

次の様に生成される:

redirect_to users_path, notice: "User has been created"

--old-style-hashオプションで、Ruby1.9においても古いスタイルで生成できる。

  • scaffold_controllerジェネレータをXMLの代わりにJSONのフォーマットブロックを生成するように変更した。

  • minitestで実行される時は、test_help.rbに自然言語テストケース名を追加(Ruby 1.9.2+)

  • コンソールへ結果をインラインで表示する為、ActiveRecordのログ出力を直接標準出力にした。

  • Rack::SSLミドルウェアをロードし、config.force_sslを追加した。全てのリクエストを強制的にHTTPSプロトコルにする。

  • テストの為、gemspecとtestsとdummyアプリケーションと共にpluginを生成する、rails plugin newコマンドを追加した。

  • オプションとしてjquery/prototypeを伴った-jパラメータを追加した。rails new myapp -j jqueryでjQueryアプリを作成できる。デフォルトはまだPrototype。

  • デフォルトのミドルウェアスタックに、Rack::EtagとRack::ConditionalGetを追加した。

  • デフォルトのミドルウェアスタックに、Rack::Cacheを追加した。

  • Engineは、Rackアプリケーションである。

  • Engineに、ミドルウェアスタックを追加した。

  • Engineは、プラグインをロードできる。

  • Engineは、自身のenvironmentファイルをロードできる。

  • 逆にアプリケーションから、Engineのルートヘルパーを呼び出すためのヘルパーを追加した。

  • アプリケーションのdb/migrateディレクトリにpluginsとenginesのマイグレーションをコピーするためのタスク。

  • 複数のディレクトリを操作できるように、ActionDispatch::Staticを変更した。

  • 分離したEngineとしてセットする為、Engineにisolate_namespace()メソッドを追加した。

  • アプリケーションにプラグインと共有Engineから全てのヘルパーを含める。

Action Pack 3.1 RC4

  • SafeBuffer文字列を受けたら、escape_jsがSafeBuffer文字列を返すのを確かめる

  • 新しいSafeBuffer制限でも正しく機能するようにescape_jsを修正

  • i18nでの名前空間化されたモデルにとっての他の規約を後退させた。

将来の廃止まで、キーは"namespace.model"形式と"namespace/model"の両方が利用可能

  • in-place SafeBufferの変更は禁止された

SafeBufferの古い振る舞いでは、sub!の様なメソッドを経て、in placeな文字列の変更をあなたに許しており、safe bufferは、安全としてマークされ続けるだろう。

例の問題はこんな感じだ:

<%= link_to('hello world', @user).sub!(/hello/, params[:xss])  %>

上の例では、untrustedな文字列 (params[:xss]) はlink_toによって返されるsafe bufferに追加され、そしてuntrustedなコンテントはescape無しでのクライアントへの送信に成功する。これを避ける為に、他の似たメソッドはsafe bufferで呼ばれた場合、今や例外を発生させるだろう。 in-placeバージョンに加えて、それらの文字列のコピーを返すメソッドのバージョンの幾つかは、不正確に安全としてマークされるだろう。例えば:

<%= link_to('hello world', @user).sub(/hello/, params[:xss]) %>

新しいバージョンは、全ての そのようなメソッドによって返される文字列は、unsafeとしてマークされる事を保証するだろう。

この変更についてはこれを見よ http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2e516e7acc96c4fb

  • CSRFトークン認証を確認できない場合はWarn

  • datatime選択にAM/PM形式を許す

  • 例外画面に、標準のENVメソッドをダンプするのみにした(rackのくず(?)全てでは無く)

  • auto_linkが置き換え方法無しに削除された。もし必要ならrails_autolink gem: http://github.com/tenderlove/rails_autolink をインスールする事で利用可能。

  • streamingサポートを追加。

class PostsController < ActionController::Base
  stream :only => :index
end

より詳細情報はActionController::Streamingのドキュメントを読んで。

  • acceptヘッダを無視するためにActionDispatch::Request.ignore_accept_headerを追加し、パラメータとして与えられているフォーマットを考慮するのみ。

  • ActionView::Rendererが作成され、ActionView::ContextにAPIを仕様にした。より詳細情報はそれぞれのオブジェクトをチェックせよ。

  • パラメータをネストしたハッシュにラップする為に、ActionController::ParamsWrapper`を追加した。デフォルトで新しいアプリケーションにおけるJSONリクエストの為になっているだろう(?)

これはconfig/initializer/wrap_parameters.rbActionController::Base.wrap_parametersを設定することにより、カスタマイズできる。

例えば、このルーティングなら

map '*pages' => 'pages#show'

'/foo/bar.json'をリクエストする事によってルーティングできる。params[:pages]は、JSONフォーマットで、"foo/bar"と等しいだろう。もし古い3.0.xの振る舞いへ戻したいなら、:format => falseを渡すことで実現できる。

map '*pages' => 'pages#show', :format => false
  • 単一のクラスメソッド呼び出しで、ベーシック認証を設定できるBase.http_basic_authenticate_withを追加。
class PostsController < ApplicationController
  USER_NAME, PASSWORD = "dhh", "secret"

  before_filter :authenticate, :except => [ :index ]

  def index
    render :text => "Everyone can see me!"
  end

  def edit
    render :text => "I'm only accessible if you know the password"
  end

  private
    def authenticate
      authenticate_or_request_with_http_basic do |user_name, password|
        user_name == USER_NAME && password == PASSWORD
      end
    end
end

..下記のように記述できる。

class PostsController < ApplicationController
  http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index

  def index
    render :text => "Everyone can see me!"
  end

  def edit
    render :text => "I'm only accessible if you know the password"
  end
end
  • 特定のアクションにhttpsプロトコルを強制する為にforce_sslの追加を許す。:onlyやら:exceptも使える。

  • FormHelper#form_forで、:methodを直接指定できるようにする。

form_for(@post, remote: true, html: { method: :delete }) の代わりに form_for(@post, remote: true, method: :delete)
  • JavaScriptHelper#escape_javascript()のエイリアスをJavaScriptHelper#j()にする。 JavaScriptHelperを利用する時、JSON gemが追加するObject#j()メソッドに取って代わる。

  • (config.filter_parametersで指定された)機密なクエリー文字列パラメータは、ログファイルにおいてリクエストパスからフィルターされるだろう。 (訳注 logに出力されるurl変数もフィルターするよという意味でしょう。 https://github.com/rails/rails/commit/68802d0fbe9d20ef8c5f6626d4b3279bd3a42d3e)

  • (↓で削除されていた)to_paramがfalseを返すURLパラメータは、クエリー文字列に現れる。

  • to_paramがnilを返すURLパラメータは、クエリー文字列から削除された。

  • ActionDispatch::MiddlewareStackは継承より(?)コンポジションを使う。It is no longer an array which means there may be methods missing that were not tested.

  • カスタマイズの為もしくはトークンを省略する(:authenticity_token => falseを渡す)為に、form_tagに:authenticity_tokenオプションを追加した。

  • HTML5のbutton_tag ヘルパーを追加する。

  • テンプレートルックアップは継承チェーンを逆上りながら探す。

  • テンプレートをキャッシュするかどうか決定する為に、config.action_view.cache_template_loadingを復活した。

  • url_forと名前付きurlヘルパーは、オプションに:subdomainと:domainを受け付ける。

  • リダイレクトルートメソッドは、質問のurlの部分を変えるためだけのオプションのハッシュや、(リダイレクトを再利用する為)callが呼び出せるオブジェクトを許す。(訳注 https://github.com/rails/rails/commit/0bda6f1ec664fcfd1b312492a6419e3d76d5baa7)

  • config.action_controller.include_all_helpersを追加した。デフォルトでActionController::Basehelper :allされ、全てのヘルパーが含まれる。include_all_helpersをfalseに設定すると、application_helperと対応するコントローラのみ(foo_helperはfoo_controllerの様に)に追加する。

  • HTML5のdata-*属性を生成する為の便利イディオムを:dataのハッシュから渡せるように、tagヘルパーに追加した。

tag("div", :data => {:name => 'Stephen', :city_state => %w(Chicago IL)})
# => <div data-name="Stephen" data-city-state="[&quot;Chicago&quot;,&quot;IL&quot;]" />

キーはダッシュ化される。値はstringとsymbolを除いて、JSONエンコードされる。

  • :onceをrenderに追加した。stringかstringの配列のみ渡す事ができ、Railsは、それぞれ毎に一度のみレンダリングできる。(訳注 https://github.com/rails/rails/commit/940b57789fb9166658974c591e68d22ecab29f34)

  • 古いテンプレートハンドラーAPIを廃止した。新しいAPIは単純にcallを呼び出させる事を要求する。

  • :rhtmlと:rxmlは、テンプレートハンドラーとして削除された。

  • ActionDispatch::Response から、middleware stack にetagの責務を移動。

  • rubyの世界を横断する互換性向上の為にRack::Session store APIに依存する(?)。これはRack::Sessionは4引数を許す#get_sessionや、シンプルな#destroyの変わりに#destroy_session要求する、後方非互換性である。 (訳注 https://github.com/rails/rails/commit/50215f9525b6b5e3bfe703724b9f68177ed8565d)

  • file_fieldは自動的に、囲んでいるformに:multipart => trueをセットする。

  • csrf_meta_tagからcsrf_meta_tagsに変更。後方互換性の為、csrf_meta_tagは別名に。

  • デフォルトスタックにRack::Cacheを追加。Railsキャッシュへ委譲するRailsストアを作成。デフォルトではHTTPキャッシングを使う。もし:public => trueで#expires_in、#fresh_when、#staleを使うなら、Rack::Cacheは使われるだろう、一方キャッシュルールはブラウザのみに適用されるだろう。

Active Record 3.1 RC4

  • AR#pluralize_table_names は個々のモデルの単数形/複数形のテーブル名を設定可能:
class User < ActiveRecord::Base
  self.pluralize_table_names = false
end

以前は、これは全てのモデルにたいして全体のみにセットされていた。

  • 単数の関連にブロックで属性設定を追加:
class User < ActiveRecord::Base
  has_one :account
end

user.build_account{ |a| a.credit_limit => 100.0 }

ブロックは、インスタンスが初期化された後に、呼ばれる。

  • 属性の名前のリストを返すために、ActiveRecord::Base.attribute_namesを追加。もしモデルが抽象クラスであるか、テーブルが見つからない場合に、空の配列を返すだろう。

  • CSVフィクスチャーは廃止で、rails3.2.0に削除されるだろう。

  • AR#newAR#createAR#update_attributesは全て、属性割り当て時にロールを考慮する為指定される二番目のハッシュを受け取れる。これはActiveModelの新しいmass assignment機能から出来ている:

class Post < ActiveRecord::Base
  attr_accessible :title
  attr_accessible :title, :published_at, :as => :admin
end

Post.new(params[:post], :as => :admin)

同種のAPIであるassign_attributes()が追加された。またattributes=(params, guard)は廃止された。

  • 遅延評価の為、default_scopeにblockやlambdaもしくはcallを呼び出せるオブジェクトをとる事ができる。
default_scope { ... }
default_scope lambda { ... }
default_scope method(:foo)

もしActiveRecord::Relationの内部構造を詳細に調べると、(結果に含まれていても)デフォルトスコープを"含んでいない"という事を記しておく。public APIの一部ではないが、ActiveRecord#with_default_scope呼び出しによってデフォルトスコープを含んでいるリレーションを得る事ができる。

  • クラス内でのdefault_scope複数回呼び出しを(スーパークラスが呼び出す時を含め)廃止する。現在の振る舞いはマージする。
class Post < ActiveRecord::Base # Rails 3.1
  default_scope where(:published => true)
  default_scope where(:hidden => false)
  # The default scope is now: where(:published => true, :hidden => false)
end

Rails3.2では、振る舞いが前のscopeを上書きするように変わるだろう。

class Post < ActiveRecord::Base # Rails 3.2
  default_scope where(:published => true)
  default_scope where(:hidden => false)
  # The default scope is now: where(:hidden => false)
end

もしdefault scopeをマージしたかったら、クラスメソッドとしてdefault scopeを定義し、コード共有の為の標準テクニック利用を推奨する。

class Post < ActiveRecord::Base
  def self.default_scope
    where(:published => true).where(:hidden => false)
  end
end
  • PostgreSQLアダプターは8.2以上のバージョンのみサポートする。

  • ConnectionManagementミドルウェアはrackボディがflushされた後でコネクションプールをクリアするように変更された。

  • ActiveRecordにupdate_columnメソッドを追加した。これは新しいメソッドがオブジェクトの与えられた属性をvalidationやcallbackをスキップし更新する。"updated_at"の更新を含め、いかなるコールバックも実行したくないなら#update_attributeの利用を推奨する。新しいレコードには使うべきではない。

例:

User.first.update_column(:name, "sebastian")         # => true
  • :throughオプションを伴ったアソシエーションはthroughやsourceアソシエーションの様ないくつかのアソシエーションを使える(:throughオプションを持つほかのアソシエーションやhas_and_belongs_to_manyアソシエーションを含め)。

  • 現在のデータベース設定は、ActiveRecord::Base.connection_configでアクセスできる。

  • limitとoffsetの両方を呼び出しているので無ければ、COUNTクエリーからlimitとoffsetを削除する。例えば:

People.limit(1).count           # => 'SELECT COUNT(*) FROM people'
People.offset(1).count          # => 'SELECT COUNT(*) FROM people'
People.limit(1).offset(1).count # => 'SELECT COUNT(*) FROM people LIMIT 1 OFFSET 1'
  • ActiveRecord::Associations::AssociationProxyが分割された。今やAssociationクラス(とサブクラス)がアソシエーションの操作の責務を持ち、分離された、CollectionProxyと呼ばれる薄いラッパーがコレクションアソシエーションのプロキシを担う。

これは名前空間汚染を避け、関心事の分離をし、進んだリファクタリングを許すだろう。

単一アソシエーション(has_one, belongs_to)は、proxyではない。これらは単純に関連するレコードかnilを返す。これはbob.create_motherの代わりにbob.mother.createのようなドキュメント化されていないメソッドを使うべきではないという事を意味する。

  • レコードをbuildしsaveした時に、has_many :through 関連は正しく動くようにする。これはあなたにjoinモデル上のsourceリフレクションに:inverse_ofオプションをセットする事を要求する。
class Post < ActiveRecord::Base
  has_many :taggings
  has_many :tags, :through => :taggings
end

class Tagging < ActiveRecord::Base
  belongs_to :post
  belongs_to :tag, :inverse_of => :tagging # :inverse_of must be set!
end

class Tag < ActiveRecord::Base
  has_many :taggings
  has_many :posts, :through => :taggings
end

post = Post.first
tag = post.tags.build :name => "ruby"
tag.save # will save a Taggable linking to the post
  • has_many :throughアソシエーションに:dependentオプションをサポートした。歴史的かつ実践的名理由で、(通常のhas_manyにとってのデフォルト戦略が:nullifyである事実にも関わらず):delete_allassociation.delete(*records)によって使用されるデフォルト削除戦略である。また、これはソースリフレクションが、belongs_to`である場合のみ動作する。他のシチュエーションでは、throughアソシエーションを直接変更すべきである。

  • has_and_belongs_to_manyとhas_many :throughの#destroyの振る舞いを変更した。今からはアソシエーションの'destroy'や'delete'はリンクを取り除くを意味する(必ずしも関連したレコードを取り除くではなく)

以前は、has_and_belongs_to_many.destroy(*records)はレコード自身を削除した。join tableのレコードは削除しない。今や、join tableのレコードを削除する。

以前は、has_many_through.destroy(*records)はレコード自身とjoin tableのレコードを削除した。(注記: 以前のバージョンのRailsはレコード自身のみ削除という場合もあった) 今や、join tableのレコードのみ削除する。

この変更は、ある程度後方非互換性がある事を記しておく(不運にもそれを変更する前に'deprecate'する方法が無い)。変更は異なるアソシエーションを通じての'destroy'や'delete'の意味の一貫性を得る為に作られた。

もしレコード自身を削除したいなら、records.association.each(&:destroy)で可能である。

  • 一つのALTER文で全ての変更を行う為に、change_tableメソッドに:bulk => trueオプションを追加。

例:

change_table(:users, :bulk => true) do |t|
  t.string :company_name
  t.change :birthdate, :datetime
end

これは下記の用に動くだろう:

ALTER TABLE `users` ADD COLUMN `company_name` varchar(255), CHANGE `updated_at` `updated_at` datetime DEFAULT NULL
  • has_and_belongs_to_manyサポートをやめる。2006年4月に廃止される振る舞いとしてドキュメントかされている。代わりにhas_many :throughを使ってくれ。

  • has_one と belongs_to 関連に create_association! メソッドを追加。

  • モデルとXXXによりジェネレートされたマイグレーションファイルは、古いupdownメソッドの代わりにマイグレーションの(reversibleな)changeメソッドを使う。

  • アソシエーション上の補完SQLコンディション文字列のサポートをやめた。変わりにprocを使え。

前:

has_many :things, :conditions => 'foo = #{bar}'

後:

has_many :things, :conditions => proc { "foo = #{bar}" }

procの中では、eagerローディングではない場合は、'self'はアソシエーションのオーナーオブジェクトである。eagerローディングの場合は'self'はアソシエーションが入っているクラスである(?)

procの中で”通常”のコンディションも書けるので、次のコードも動く:

has_many :things, :conditions => proc { ["foo = ?", bar] }

以前has_and_belongs_to_manyアソシエーションに:insert_sqlと:delete_sqlは、登録されたり削除されたりするレコードを得るため、'record'を呼び出す事を許していた。これはprocへの引数として渡される。

  • BCryptとソルトを利用した簡単なパスワードを利用する為、(ActiveModel::SecurePasswordを経て) ActiveRecord::Base#has_secure_password を追加した。例:
# Schema: User(name:string, password_digest:string, password_salt:string)
class User < ActiveRecord::Base
  has_secure_password
end

user = User.new(:name => "david", :password => "", :password_confirmation => "nomatch")
user.save                                                      # => false, password required
user.password = "mUc3m00RsqyRe"
user.save                                                      # => false, confirmation doesn't match
user.password_confirmation = "mUc3m00RsqyRe"
user.save                                                      # => true
user.authenticate("notright")                                  # => false
user.authenticate("mUc3m00RsqyRe")                             # => user
User.find_by_name("david").try(:authenticate, "notright")      # => nil
User.find_by_name("david").try(:authenticate, "mUc3m00RsqyRe") # => user
  • modelをジェネレートする時、belongs_toやreferencesカラムの為にデフォルトでadd_indexを追加する。
rails g model post user:belongs_to は下記を生成するだろう:
class CreatePosts < ActiveRecord::Migration
  def up
    create_table :posts do |t|
      t.belongs_to :user

      t.timestamps
    end

    add_index :posts, :user_id
  end

  def down
    drop_table :posts
  end
end
  • belongs_toオブジェクトのidをセットすると、そのオブジェクトへの参照も更新するだろう。

  • ActiveRecord::Base#dupとActiveRecord::Base#cloneのセマンティクスは通常のRubyのdupとcloneのセマンティクスに近づけられた。

  • ActiveRecord::Base#cloneを呼び出す事は、レコードの浅いコピーの結果になり、frozen状態がこぴーされる(?)。コールバックは呼ばれない。

  • ActiveRecord::Base#dupを呼び出す事は、レコードを複製しafter_initializeフックを呼び出す。fronzen状態がコピーされない。全てのアソシエーションがクリアされる。dupされたレコードはnew_record?でtrueを返し、idはnilでsave可能である。

  • マイグレーションは、リバーシブルとして定義されている。そしてそれはマイグレーションシステムが、あなたのマイグレーションをどのように逆転するか示す事を意味する。リバーシブルなマイグレーションを使うためには、"change"メソッドを定義しなければいけない。例えば:

class MyMigration < ActiveRecord::Migration
  def change
    create_table(:horses) do
      t.column :content, :text
      t.column :remind_at, :datetime
    end
  end
end

自動的に反転できない場合がある。そのような場合は'up'と'down'を定義すべきである。もしchangeが反転できない場合は、IrreversibleMigration例外がdown時に発生するだろう。

  • マイグレーションはクラスメソッドより、インスタンスメソッドを使うべきである:
class FooMigration < ActiveRecord::Migration
  def up
    ...
  end
end
  • has_oneは一つのafter_saveの代わりに、分離されたafter_create / after_updateでアソシエーションを維持する。

  • 次のコード:

Model.limit(10).scoping { Model.count }

は次のSQLを生成する:

SELECT COUNT(*) FROM models LIMIT 10

望んでいる事と違う場合次の様にできる:

Model.limit(10).scoping { Model.all.size }

Active Model 3.1 RC4

  • attr_accessibleとその仲間たちは、ロールを指定する為、:asオプションを受け付ける。

  • InclusionValidator、ExclusionValidator、FormatValidatorへのオプションとして、procかlambdaを渡せるようにした。

引数として現在のレコードを受け取り、callメソッドを呼び出せる、Proc(やlambda)を渡せるようになった。Proc(やlambda)は、InclusionValidatorとExclusionValidatorでは#include?を呼び出せるオブジェクトを返す必要があり、FormatValidatorでは正規表現を返す必要がある。

  • BCryptとソルトを利用した簡単なパスワードを利用する為、ActiveModel::SecurePasswordを追加した。

  • ActiveModel::AttributeMethodsは、必要な時に定義される属性を許す。

Active Support 3.1 RC4

  • ActiveSupport::Dependenciesは、load_missing_constantに存在する定数を見つけたならNameErrorを発生させる。これは、ネストされた定数でのコンスタンタイズを呼ぶ事によっていつも起こされているエラーの自然なより良い反映である。

  • 標準ライブラリのSecureRandom を選んで、ActiveSupport::SecureRandom を廃止した。

  • 新しいレポーティングメソッド Kernel#quietly

  • stringをStringInquirerオブジェクトに変更する為の便利メソッドとして、String#inquiryを追加した。

  • オブジェクトが他のオブジェクトに含まれているかどうかテストする為にObject#in?を追加した。

  • LocalCacheストラテジーは、?(posing for pictures)の無名クラスでは無く、本当のミドルウェアクラスである。

  • 再読込可能クラスへの参照を保持する為、ActiveSupport::Dependencies::ClassCacheを追加した。

  • ClassCacheの直接の利点を得る為、ActiveSupport::Dependencies::Referenceをリファクタリングした。

  • Ruby 1.8で、Range#include?へのエイリアスとしてRange#cover?をバックポートした。

  • Date/DateTime/Timeにweeks_agoprev_weekを追加した。

  • ActiveSupport::Dependencies.remove_unloadable_constants!に、before_remove_constコールバックを追加した。

Active Resource 3.1 RC4

  • 全てのリクエストにとってのデフォルトフォーマットはJSONに変更されている。もしXMLを利用したい場合は、クラスの中で self.format = :xml をセットする必要がある。例えば:
class User < ActiveResource::Base
  self.format = :xml
end

Action Mailer 3.1 RC4

  • 変更なし。