27
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Ruby on Rails モデル内で配列型のカラムを指定する

Last updated at Posted at 2017-08-31

2017.09.02追記
Ruby on rails でArrayをようやく問題なく扱えるようになったので、解決法をご紹介します。

Ruby on railsでデータベースを扱う際に、Array型を用いようとしてかなりハマりました。
##※初心者の方へ
データベースに配列型を組み込んでしまうのは、まずあまり望ましいやり方ではありません。今後も開発をしていく上でスキルアップを目指している方は、他のやり方を試してみたほうがいいかもしれません。(データベース設計の基礎をうまく使いながら、別のテーブルにデータを写して中間テーブルで参照するなど)(参考:https://qiita.com/Kohei_Kishimoto0214/items/cb9a3d3da57708fb52c9)
それでもという方は、下記の方法を試してみてください。
##array: trueserialize を合わせて使う

#####環境
Rails 5.1.3
Ruby 2.2.3
Mac OS 10.12.4(Sierra)
ツール:Sublime Text3

##やり方
まず、コマンドでmigrationを追加します。

$ rails generate migration AddColumnToBands

次に作成されたmigrationファイルの中に以下を追加します。

db/migrate/add_column_to_bands.rb
  def change
    add_column :bands, :members, :text, array: true
    serialize :bands, Array
  end

カラムの型にはtext型を指定して、次の引数でarray: trueを指定します。
複数のデータを直列化しての送信を可能にするserializeメソッドを用いて、Array型でデータを扱えるようにします。これを追加した後、コマンドにて

$ rails db:migrate

を実行します。これによってデータがArray型で扱えるようになりました。

試した対策

###1.migration内でarrayを指定

add_column_to_bands.rb
 add_column :bands, :members, :string, default: [], array: true

ターミナルでmigrateしてみると、"can't quote array というエラーが。"

 -- add_column(:bands, :members, :text, {:default=>[], :array=>true})
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

can't quote Array

###2.migration内でdefault: [].to_yamlを指定

add_column_to_bands.rb
 add_column :bands, :members, :string, default: [].to_yaml, array: true

migrationは成功するものの、実際に動かしてみると配列型にはなっていません。

###3.一度モデル自体を消去して、新しいモデルを作成

class CreateBands < ActiveRecord::Migration[5.1]
  def change
    create_table :bands do |t|
      t.string :name
      t.string[] :members #
      t.text :description
      t.string :image
      t.timestamps
    end
  end
end

こちらも②と同じ結末に。
##仮説
####①Railsで作成されるModelがそもそも配列型に対応していない
以前SwiftでNCMBを使用していた際は、データベースが配列型に対応していたので直接引っ張って処理が可能でしたが、Ruby on railsでは配列型に対応しておらず、String型で格納して引っ張り出した時に変換するしかないのではないのか??という一つの仮説に行き着きました。
#####sakuroさんのコメントより
Railsのモデルはarray型に対応しており、非対応のversionの場合は、text型にしてモデル内でserializeを行います。

####②なんらかの方法はあるが、インターネット上では簡潔な対策が見つからない
1時間ほどリサーチしましたが、基本的に回りくどいやり方(初心者なのが原因かもしれませんが)しか発見することができなかったので、実はなんらかの方法があるものの、それが一切ネット上には乗っていないのかもしれない。

②の仮説はあまりにも時代に合わないので、①こそが原因だろうと結論付けて解決策をまとめました

##解決策
###1.配列自体をString型で扱う
あまりいい方法ではないとは思いますが、その配列を使用する時に毎度配列型に変換するというやり方です。
###2.他のテーブルを作る
従属性のあるもう一つのテーブルを作る
あるテーブルに関連づけて他のテーブルを作成し、そこから値を引っ張ってくるというやり方です。ある項目一つをキーにして、他のテーブルから持ってくるというやり方を取る方法です。一応のところ解決できました。

class CreateBands < ActiveRecord::Migration[5.1]
  def change
    create_table :bands do |t|
      t.string :name
      t.text :description
      t.string :image
      t.timestamps
    end
  end
end

class CreateBandMembers < ActiveRecord::Migration[5.1]
  def change
    create_table :bands do |t|
      t.string :name
      t.string :member1
      t.string :member2
      t.string :member3
      t.string :member4
    end
  end
end

###3.モデル内でserializeを行う

class CreateBands < ActiveRecord::Migration[5.1]
  def change
    create_table :bands do |t|
      t.string :name
      t.text :members, array: true #これで解決しない場合 
      t.string :image
      t.timestamps
    end
  end
end

(seriarizeについては追記予定)

良い解決策があれば是非ご教授願いたいと思います。

27
19
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?