Rails 4.1のenumの挙動(2)
前回、キーの項目と数値を定義したのだけど、実はキーの項目だけ指定しても数値として保存されるようだ(キーだけだと文字列で保存されるのかと思っていた……)。
class Product < ActiveRecord::Base enum status: %w(normal sale empty) end
こんな感じで定義してから ./bin/rails c
して確認する。
まずはどのようにデータが保存されるか。
Loading development environment (Rails 4.1.0.rc2) irb(main):001:0> Product.create(status: 1) (0.2ms) begin transaction SQL (0.9ms) INSERT INTO "products" ("created_at", "status", "updated_at") VALUES (?, ?, ?) [["created_at", "2014-04-06 02:53:47.039739"], ["status", 1], ["updated_at", "2014-04-06 02:53:47.039739"]] (1.3ms) commit transaction => #<Product id: 1, name: nil, status: 1, created_at: "2014-04-06 02:53:47", updated_at: "2014-04-06 02:53:47"> irb(main):002:0> Product.create(status: "sale") (0.2ms) begin transaction SQL (0.4ms) INSERT INTO "products" ("created_at", "status", "updated_at") VALUES (?, ?, ?) [["created_at", "2014-04-06 02:53:57.177845"], ["status", 1], ["updated_at", "2014-04-06 02:53:57.177845"]] (1.0ms) commit transaction => #<Product id: 2, name: nil, status: 1, created_at: "2014-04-06 02:53:57", updated_at: "2014-04-06 02:53:57"> irb(main):003:0> Product.create(status: :sale) (0.2ms) begin transaction SQL (0.6ms) INSERT INTO "products" ("created_at", "status", "updated_at") VALUES (?, ?, ?) [["created_at", "2014-04-06 02:54:05.389452"], ["status", 1], ["updated_at", "2014-04-06 02:54:05.389452"]] (1.3ms) commit transaction
ついでに、前回は書かなかったんだけど述語メソッドも生えているのでそっちも確認しておく。ここで保存したのはsaleの値なので、sale?で問い合わせすることができる。
irb(main):013:0> pro = Product.where(status: 1).first Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."status" = 1 ORDER BY "products"."id" ASC LIMIT 1 => #<Product id: 1, name: nil, status: 1, created_at: "2014-04-06 02:53:47", updated_at: "2014-04-06 02:53:47"> irb(main):014:0> pro.sale? => true
ここではどうでも良いけど、empty
ってステータスはメソッド呼び出しだとちょっと誤解を招きそうなので辞めたほうが良いですね。
検索する場合、ステータス毎のクラスメソッドがある。当然、メソッドチェインでwhere区等もつなげることができる。
irb(main):003:0* Product.sale Product Load (3.3ms) SELECT "products".* FROM "products" WHERE "products"."status" = 1 => #<ActiveRecord::Relation [#<Product id: 1, name: nil, status: 1, created_at: "2014-04-06 02:53:47", updated_at: "2014-04-06 02:53:47">, #<Product id: 2, name: nil, status: 1, created_at: "2014-04-06 02:53:57", updated_at: "2014-04-06 02:53:57">, #<Product id: 3, name: nil, status: 1, created_at: "2014-04-06 02:54:05", updated_at: "2014-04-06 02:54:05">]> irb(main):004:0> Product.sale.where('id > 2') Product Load (0.4ms) SELECT "products".* FROM "products" WHERE "products"."status" = 1 AND (id > 2) => #<ActiveRecord::Relation [#<Product id: 3, name: nil, status: 1, created_at: "2014-04-06 02:54:05", updated_at: "2014-04-06 02:54:05">]>
ただ、where区に文字列やシンボルで渡しても想定通りの動作にはならない。シンボルはともかく、文字列を渡すと0で検索しちゃうのはウッカリハマる可能性がありそう……。
irb(main):008:0> Product.where(status: 'sale') Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."status" = 0 => #<ActiveRecord::Relation []> irb(main):009:0> Product.where(status: :sale) Product Load (0.4ms) SELECT "products".* FROM "products" WHERE "products"."status" = 'sale' => #<ActiveRecord::Relation []>
私からは以上です。