開発ブログ

株式会社Nextatのスタッフがお送りする技術コラムメインのブログ。

電話でのお問合わせ 075-744-6842 ([月]-[金] 10:00〜17:00)

  1. top >
  2. 開発ブログ >
  3. Ruby >
  4. Ruby on Rails >
  5. Rails4の抽象クラス(Model)に定義したscopeが変なSQLを吐く件
no-image

Rails4の抽象クラス(Model)に定義したscopeが変なSQLを吐く件

railsでは簡単な設定によりテーブルを持たないモデルを作成する事ができます。
複数のモデルに共通する設定やメソッドなどを1箇所に書くことが出来て便利です。

今回はRails4において、scopeを定義した抽象クラスを継承した子クラスでscopeを利用した際に遭遇したエラーについてです。
ちなみに根本的な解決策は見つけていません。

抽象クラスとscopeを定義して(self.abstract_class = true)
#app/models/abstract_model.rb
class AbstractModel < ActiveRecord::Base
  self.abstract_class = true
  scope :latest, -> { order("created_at DESC") }
end
継承してサブクラスを定義
#app/models/foo.rb
class Foo < AbstractModel
end
そしてサブクラスでscopeを利用すると
#app/controllers/foo_controller.rb
class FooController < ApplicationController
  def bar
    @foos = Foo.latest
  end
end

#app/views/foo/bar.html.erb
<% @foos.each do |foo| %>
  <%= foo.name %>
<% end %>
このようなエラーが
ActionView::Template::Error: Mysql2::Error: Incorrect table name '': SHOW FULL FIELDS FROM ``

SQLが自動生成された際にテーブル名が空になってしまっています。
どうもActiveRecordの問題のようなので簡単には直せそうにありません。

Githubで見つけた関連Issue

Scopes defined on Abstract ActiveRecord classes are missing table names when called from subclasses · Issue #10658 · rails/rails · GitHub

SQLを生成する際に抽象クラスのテーブル名(当然空)を参照してしまっていることが原因?

対策

場当たり的な解決策としてscopeを親クラスに記述することを諦めて
子クラスでscopeをそれぞれ定義して乗り切っています。DRY(笑)

抽象クラスを使うのを諦めてModuleでスコープを定義して使いまわすのはありかもしれません。
TOPに戻る