Railsでテーブルを結合できなくてハマった件

どうも。まずは先日サイトにアクセスできなくなっていたことをお詫び申し上げます。このブログを管理しているXserverさんが攻撃されていたらしく、サイトのサーバーがアクセス不可になっていたそうです。現在は復旧していますので、安心してブログを読み進めてくださいね。

 

さて、本題に入りますが、Ruby on railsで開発をしている際、データベースを使うという方は多いと思います。Ruby on railsではマイグレーションファイルを作ってrake db:migrateするだけで簡単にデータベースのテーブルやカラムを追加できますし、制約の追加なんかも簡単にできます。私はMySQLを使用しているのですが、今回使用しているデータベースのテーブルを結合する必要が出てきました。なので、内部結合をしようと思ったのですがなかなかうまくいかずハマってしまったというわけです。

テーブルの結合にはjoinsを使う。

railsでデータベースのテーブルを結合するときは、いくつか方法があるそうなのですが、私はjoinsというものを使っています。具体的には以下のような記述ができます。
usersとprofileというテーブルがあったと仮定すると、usersのprofile_idとprofileのidを紐付けたい場合、

    User.select('users.*,profiles.*').joins(:profiles).where(id=1)

このように書けば、紐付けをすることができます。また、上に書いたように、where属性でレコードを絞り込むことも可能です。
しかしただこれをするだけではうまくいきませんでした。これがハマった原因でした。
 

モデルファイルに外部キーを追加しなければいけなかった。

joinsを使って紐付けをするためには、モデルの外部キーをあらかじめ設定してやる必要があった。これをしないと、
ActiveRecord::StatementInvalid: Mysql2::Error: Unknown column ” in ‘on clause’: SELECT .* FROM “ INNER JOIN “ ON なんちゃら〜〜というエラーを吐いてしまいます。

具体的にどのように外部キーを設定すれば良いのかというと、テーブル同士が1対1で紐付くのか、多対1で紐付くのかなどによって使い分けた方がいいのですが、とりあえず以下でエラーは吐かず正常にテーブルを結合することができます。
Userのモデルには

class User < ApplicationRecord
  has_many :profiles,foreign_key: "id"
end

と追記。
Profileのモデルには

class Profile < ApplicationRecord
  has_many :users,foreign_key: "profile_id"
end

と追記します。

joinsで結合した場合、結合した側のカラムの値を取り出すには・・・

joinsを使って結合すると、そのまま書くと結合した側のカラムを取り出すことができません。なので、attributesというものを使うことで取り出せるようになります。具体的には、以下のようにすればすべて出力できます。

    User.select('users.*,profiles.*').joins(:profiles).where(id=1).each do |t|
     p t.attributes["結合した側のカラム名"]
    end

まとめ

今回はRailsでテーブルを結合できなくてハマったことについて書きました。みなさんもしjoinsで結合がうまくいかないようなら、外部キーを設定しているかを確認してみてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です