【Rails】Railsのバグ?joinsを使ってハマるパターン
Railsで新しい検索条件(scopeなどでjoinsを使用)を追加した時にハマりました。
最近、ハマってしかない。。。。
前提条件
- shopsテーブルには「company_id」が存在する。
- companysテーブルには「shop_id」が存在する。
- shop_profilesテーブルには「shop_id」は存在するが、「company_id」は存在しない。
- shop_profilesテーブルには「g08m11_code」が存在する。
- 検索対象は「g08m11_code」
こけるパターン
shops.rb
class Shop < ApplicationModel has_one :shop_profile, :dependent => :destroy scope :g08m11_code_is, lambda { |g08m11_code| joins(:shop_profile).where("shop_profiles.g08m11_code like ?", "%#{g08m11_code}%") unless g08m11_code.blank? } def self.find_by_search_form(form) g08m11_code_is(form.g08m11_code) end end
shops_profiles.rb
class ShopProfile < ActiveRecord::Base belongs_to :shop scope :g08m11_code_is, lambda { |g08m11_code| where("g08m11_code like ?", "%#{g08m11_code}%") unless g08m11_code.blank? } end
company.rb
class Company < ApplicationModel has_many :shops companies = companies.joins(:shops).merge(Shop.find_by_search_form(shop_search_form)) end
エラー内容
Completed 500 Internal Server Error in 937ms ActiveRecord::ConfigurationError (Association named 'shop_profile' was not found; perhaps you misspelled it?)
shop_profileなんてないよ。タイプミスしてない?って怒られます。
試み
company側にshopsと同じ定義を書いてみたらどうか
Associationに関するエラーということから、
company側にShopと同じような記述を書いて見たらと考える。
class Company < ApplicationModel has_many :shops #追加部分 has_one :shop_profile end
結果
[2014-03-04 18:49:05.778375 #6976][DEBUG] -- : Mysql2::Error: Unknown column 'shop_profiles.company_id' in 'on clause': SELECT COUNT(*) FROM `companies` INNER JOIN `shops` ON `shops`.`company_id` = `companies`.`id` INNER JOIN `shop_profiles` ON `shop_profiles`.`company_id` = `companies`.`id` WHERE (companies.deleted_at IS NULL) AND (shops.deleted_at IS NULL) AND (shop_profiles.g08m11_code like '%111111%') 500 Internal Server Error If you are the administrator of this website, then please read this web application's log file and/or the web server's log file to find out what went wrong.
最終的に落ち着いたコードは以下のとおり。
こけないパターン
shops.rb
class Shop < ApplicationModel has_one :shop_profile, :dependent => :destroy scope :g08m11_code_is, lambda { |g08m11_code| joins("join shop_profiles on shop_profiles.shop_id = shops.id").merge(ShopProfile.g08m11_code_is(g08m11_code)) unless g08m11_code.blank? } def self.find_by_search_form(form) g08m11_code_is(form.g08m11_code) end end
shops_profiles.rb
class ShopProfile < ActiveRecord::Base belongs_to :shop scope :g08m11_code_is, lambda { |g08m11_code| where("g08m11_code like ?", "%#{g08m11_code}%") unless g08m11_code.blank? } end
company.rb
class Company < ApplicationModel has_many :shops companies = companies.joins(:shops).merge(Shop.find_by_search_form(shop_search_form)) end