8880


Rails3.2でHABTM(Has And Belongs To Many)を実装しました。

prefectures，schoolsがそれぞれHABTMの関係になっており、

中間テーブルがhbtmsとなっております。

prefecture.rb

[code]

    class Prefecture < ActiveRecord::Base
      attr_accessible :name
    
      has_many :hbtms, :foreign_key => :prefecture_id
      has_many :schools, :through => :hbtms
    end
    
[/code]

school.rb

[code]

    class School < ActiveRecord::Base
      attr_accessible :name
    
      has_many :hbtms, :foreign_key => :school_id
      has_many :prefectures, :through => :hbtms, :order => "hbtms.position"
    end
    
[/code]

hbtm.rb

[code]

    class Hbtm < ActiveRecord::Base
      attr_accessible :school_id, :prefecture_id, :position
    
      belongs_to :school
      belongs_to :prefecture
    end
    
[/code]

migration（hbtmのみ 他を載せると多くなるので）

[code]

    class CreateHbtms < ActiveRecord::Migration
      def change
        create_table :hbtms, id: false  do |t|
    
          t.references :prefecture, index: true, null: false
          t.references :school, index: true, null: false
          t.integer    :position
    
    
          t.timestamps
        end
      end
    end
    
[/code]

### 質問1

中間テーブルにレコードを追加（多対多のレコード）するときは

[code]

    Prefecture.find(1).schools << School.find(2)
    
[/code]

このように実行しております。

これ以外に値を追加する方法はないでしょうか？

### 質問2

hbtmテーブルはpositionカラムがあり、ソート順に使おうと思っております。

しかし、このレコードの追加方法ですとpositionに値を設定できません。

そこで、`Hbtm.all.last.update_attributes(:position => 9)`と後で変更する際、

このようにエラーが出力されます。

[code]

    1.9.3-p551 :033 > Hbtm.all.last.update_attributes(:position => 9)
      Hbtm Load (21.3ms)  SELECT `hbtms`.* FROM `hbtms` 
       (1.1ms)  BEGIN
       (2.8ms)  UPDATE `hbtms` SET `position` = 9, `updated_at` = '2015-04-07 13:09:52' WHERE `hbtms`.`` IS NULL
    Mysql2::Error: Unknown column 'hbtms.' in 'where clause': UPDATE `hbtms` SET `position` = 9, `updated_at` = '2015-04-07 13:09:52' WHERE `hbtms`.`` IS NULL
       (0.1ms)  ROLLBACK
    ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column 'hbtms.' in 'where clause': UPDATE `hbtms` SET `position` = 9, `updated_at` = '2015-04-07 13:09:52' WHERE `hbtms`.`` IS NULL
    
[/code]

なぜエラーとして扱われるのでしょうか？

### 質問3

また、Hbtm.lastを実行するとこのようなエラーが出力されます。

[code]

    1.9.3-p551 :032 > Hbtm.last
      Hbtm Load (38.6ms)  SELECT `hbtms`.* FROM `hbtms` ORDER BY `hbtms`.`` DESC LIMIT 1
    Mysql2::Error: Unknown column 'hbtms.' in 'order clause': SELECT  `hbtms`.* FROM `hbtms`  ORDER BY `hbtms`.`` DESC LIMIT 1
    
[/code]

なぜエラーとして扱われるのでしょうか？


CC BY-SA 3.0
2015-04-07T13:13:00.090
8873
2015-04-07T18:25:38.057
2015-04-07T18:10:54.707
85
8475
question
ruby-on-rails
Rails3.2でHABTMのレコードを操作したい


### 質問1

hbtm作成時にpositionも一緒に設定したいというのであれば、こんなコードが使えます。

[code]

    Hbtm.create(prefecture: Prefecture.find(1), school: School.find(2), position: 9)
    
[/code]

### 質問2、3

それぞれ、以下のSQLが不正です。（カラム名が空）

[code]

    -- 質問2
    WHERE `hbtms`.`` IS NULL
    
    -- 質問3
    ORDER BY `hbtms`.`` 
    
[/code]

カラム名が空になる理由はhbtmsにidがない（明示的なプライマリキーがない）ためです。

[code]

    create_table :hbtms, id: false
    
[/code]

中間テーブルであってもidは持っておいた方が良いと思います。  
でないと「Railsのレールに乗っていない」状況になるため、今後もいろいろとややこしい問題に遭遇するリスクが高いです。

どうしてもidを持ちたくないというのであれば、以下のサイトで説明されているように独自のプライマリキーを持たせる方法もあるようですが、僕はめったにこういった手法は使わないですし、オススメはしません。

<http://www.bigastronaut.com/blog/2014/riding-rails-with-a-composite-primary-
key>


CC BY-SA 3.0
2015-04-07T18:25:38.057
8880
2015-04-07T18:25:38.057
85
8873
answer