

railsでマイグレーションファイルに値を設定するにはどうしたらいいですか?

たとえば、`Sex`というモデルには

  * 男性
  * 女性

というデータが入ると決まっているので、  
`rake db migrate`した時にデータはすでに入っていて欲しいんです。


CC BY-SA 3.0
2015-04-11T01:38:18.043
9036
2015-05-13T01:03:18.773
5855
question
ruby-on-rails
railsでマイグレーションファイルに値を設定する方法


デフォルト値を設定するにはdefaultオプションを利用します。

以下、userモデルのsexの値にデフォルトで0を設定する方法になります。

[code]

    class CreateUsers < ActiveRecord::Migration
      def change
        create_table :users do |t|
          t.integer :sex, null: false, default: 0 # この行が重要
    
          t.timestamps null: false
        end
      end
    end
    
[/code]


CC BY-SA 3.0
2015-04-11T03:12:24.453
9038
2015-04-11T03:12:24.453
8351
9036
answer


テーブルの作成と同時に、データを入れるのであれば、`rake db:seed` をお調べになると宜しいかと思います。

[railsで初期データを入れる(seed-fuの使い方) -
Qiita](http://qiita.com/ko2ic/items/be96e450a33d631e0059)


CC BY-SA 3.0
2015-04-13T07:07:17.997
9102
2015-04-13T07:07:17.997
7471
9036
answer


あまり推奨されない方法ですが。  
どうしてもmigrationで対応したいという話であればmigration内でもexecute出来るので利用してください。  
※ enum型とか特殊な型とか。execute使う場合は、時々あります。

この方法は「もう運用（試験）データも入ってるんだけど、マスターテーブルが追加された」という状況ぐらいでしか使わないほうがいいでしょう。  
それもそのうち  
「db:seedマスターデータだけを入れる」  
「db:seedも世代管理する」  
「db:seedは、id値も固定できるようtruncateとかするかコード値でリレーションする」  
「試験データは、別のタスクで入れる」  
「手順書のチェックシートを作って、マスターデータの追加は、migrationで投入しない」  
などの様々な方向を、考えだす機会があると思います。  
（どういう方針とするかは、ケースバイケースですし。別の話題なのでここでは触れません）


CC BY-SA 3.0
2015-05-12T06:45:05.403
10073
2015-05-12T06:45:05.403
8335
9036
answer


初期値をマイグレーション時に投入するのは、文字通りであればtutinocoさんの言う通り、default
を使う書き方くらいしか簡単にできる方法はないと思います。  
初期データを入れたいということであればuser3758624さんとNorikaz Ishiiさんの言う通りと思います。

それと別の方向性として、テーブルに登録される値を制限、所謂Enum化したい用途であれば、enumerize という gem を使う方法もあります。  
<https://github.com/brainspec/enumerize>

Gemfileを編集後bundleし、  
Gemfile:  
gem 'enumerize' # <= これを追加

試しにモデルを1つ作ってみます。  
$rails generate model human name:string sex:string age:integer

そのモデルを以下のように書きかえ、

[code]

    class Human < ActiveRecord::Base
      extend Enumerize
    
      enumerize :sex, in: [:male, :female], default: :male
    end
    
[/code]

コンソールで動作を試すと次のようになりますので、今後sexの入力値制限として使えますし、この状態でseedを作る方がモデルをnewした段階で初期値が入るのも含めて多少簡単になるかもしれません。

[code]

    $rails c
    irb(main):001:0> h = Human.new
    => #<Human id: nil, name: nil, age: nil, sex: "male", created_at: nil, updated_at: nil>
    irb(main):002:0> h.sex = 'aiu'
    => "aiu"
    irb(main):003:0> h.save
       (0.4ms)  begin transaction
       (0.6ms)  rollback transaction
    => false
    irb(main):004:0> h.sex = 'female'
    => "female"
    irb(main):005:0> h.save
       (0.4ms)  begin transaction
      SQL (0.5ms)  INSERT INTO "humen" ("sex", "created_at", "updated_at") VALUES (?, ?, ?)  [["sex", "female"], ["created_at", "2015-05-13 00:53:19.113948"], ["updated_at", "2015-05-13 00:53:19.113948"]]
    (3.5ms)  commit transaction
    => true
    
[/code]


CC BY-SA 3.0
2015-05-13T01:03:18.773
10094
2015-05-13T01:03:18.773
9403
9036
answer