2017.09.02追記
Ruby on rails でArrayをようやく問題なく扱えるようになったので、解決法をご紹介します。
Ruby on railsでデータベースを扱う際に、Array型を用いようとしてかなりハマりました。
##※初心者の方へ
データベースに配列型を組み込んでしまうのは、まずあまり望ましいやり方ではありません。今後も開発をしていく上でスキルアップを目指している方は、他のやり方を試してみたほうがいいかもしれません。(データベース設計の基礎をうまく使いながら、別のテーブルにデータを写して中間テーブルで参照するなど)(参考:https://qiita.com/Kohei_Kishimoto0214/items/cb9a3d3da57708fb52c9)
それでもという方は、下記の方法を試してみてください。
##array: true
と serialize
を合わせて使う
#####環境
Rails 5.1.3
Ruby 2.2.3
Mac OS 10.12.4(Sierra)
ツール:Sublime Text3
##やり方
まず、コマンドでmigrationを追加します。
$ rails generate migration AddColumnToBands
次に作成されたmigrationファイルの中に以下を追加します。
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 :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 :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については追記予定)
良い解決策があれば是非ご教授願いたいと思います。