複数項目のユニーク制約の付け方、解除の仕方。
複数項目でのユニーク制約を付けたい場合、次のようにするのがよい。
class CreateTouhyous < ActiveRecord::Migration def self.up add_index "touhyous", ["touhyounin_id", "gian_id"], :unique => true end def self.down remove_index "touhyous", ["touhyounin_id", "gian_id"] end end
* remove_indexの第二引数はインデックス名じゃなくて、索引対象となる項目名(またはその配列)なのね・・。
-
-
- -
-
本来のSQL文であれば「ALTER TABLE `touhyous` ADD UNIQUE `touhyous_touhyounin_id_gian_id` (`touhyounin_id`,`gian_id`)"」になるはずだと思う。
そこで、最初、マイグレーションファイルで
execute "ALTER TABLE `touhyous` ADD UNIQUE `touhyous_touhyounin_id_gian_id` (`touhyounin_id`,`gian_id`)"
(↑)と書いて実行した。しかし、schema.rb を見たら、こんなの(↓)ができていた。
add_index "touhyous", ["touhyounin_id", "gian_id"], :name => "touhyous_touhyounin_id_gian_id", :unique => true
-
-
- -
-
それはそれで、目的の機能を実現していることになる。
しかし、downメソッドでの書き方は、どうなんでしょ?
こんな風(↓)に書いてみたら・・
def self.down execute "ALTER TABLE `touhyous` DROP UNIQUE `touhyous_touhyounin_id_gian_id`" end
やはり、思った通り、バージョンダウンで失敗。
rake aborted! Mysql::Error: #42000 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE `touhyous_touhyounin_id_gian_id`' at line 1: ALTER TABLE `touhyous` DROP UNIQUE `touhyous_touhyounin_id_gian_id` (See full trace by running task with --trace) ここをクリックし、追跡を有効にしてタスクを再実行してください
まあ、これは MySQLの癖の問題なのだろう。しかし、
remove_index "touhyous", "touhyous_touhyounin_id_gian_id"
でも失敗。
rake aborted! Mysql::Error: #42000 Can't DROP 'index_touhyous_on_touhyous_touhyounin_id_gian_id'; check that column/key exists: DROP INDEX `index_touhyous_on_touhyous_touhyounin_id_gian_id` ON touhyous (See full trace by running task with --trace) ここをクリックし、追跡を有効にしてタスクを再実行してください -- remove_index("touhyous", "touhyous_touhyounin_id_gian_id")
念のため、作り方を変更して、次のようにして
add_index "touhyous", ["touhyounin_id", "gian_id"], :name => "touhyous_touhyounin_id_gian_id", :unique => true
で作ってみる。しかし、出てきた schema.rb は当然同じ同じものなので、削除はやはり、失敗する。
そもそも、「DROP INDEX `index_touhyous_on_touhyous_touhyounin_id_gian_id`」って、名前が違うじゃん。バグかな?
* テーブルごとDROPすればインデックスも消えるので、実害は無いのだが・・。
-
-
- -
-
これ(↓)が正解のようだ。
class CreateTouhyous < ActiveRecord::Migration def self.up add_index "touhyous", ["touhyounin_id", "gian_id"], :unique => true end def self.down remove_index "touhyous", :column => ["touhyounin_id", "gian_id"] end end
-
-
- -
-
投票用紙
バサッと作る。
class Touhyou < ActiveRecord::Base # # 議案モデルから投票モデルを作る # 投票人モデルをスキャンして投票人モデルidを取出す。 # def self.create_by_gian(gian) gian_id = gian.id soukai_id = gian.soukai.id sql =<<MMMM insert into touhyous ( gian_id , touhyounin_id ) select #{gian_id} ,id from touhyounins as t where t.soukai_id = #{soukai_id} MMMM # logger.warn connection.class.to_s #=>ActiveRecord::ConnectionAdapters::MysqlAdapter connection.execute(sql) # , :soukai_id=>soukai_id, :gian_id=>gian_id) end # # 投票人モデルから投票モデルを作る # 議案モデルをスキャンして議案モデルidを取出す # def self.create_by_touhyounin(touhyounin) touhyounin_id = touhyounin.id soukai_id = touhyounin.soukai.id sql =<<MMMM insert into touhyous ( gian_id , touhyounin_id ) select id , #{touhyounin_id} from gians as t where t.soukai_id = #{soukai_id} MMMM # logger.warn connection.class.to_s #=>ActiveRecord::ConnectionAdapters::MysqlAdapter connection.execute(sql) end end
class GiansController < ApplicationController ・・・・ def create @gian = Gian.new(params[:gian]) respond_to do |format| if @gian.save Touhyou.create_by_gian(@gian) # ←★ # flash[:notice] = 'Gian was successfully created.'
バサッと消す。
class Touhyounin < ActiveRecord::Base belongs_to :soukai has_many :touhyous , :dependent=>:delete_all # ←★
class Gian < ActiveRecord::Base belongs_to :soukai has_many :touhyou , :dependent => :delete_all # ←★