While working on a Rails 3 project, I've stumbled across an
issue concerning the use of arel methods in scopes instead of the
soon to be deprecated hash syntax. The issue arises if a model's
table doesn't exist yet but the model is being loaded as part of
the environment – which, for example, happens if an observer
is defined on said model or if initializers load/extend a
model.
# app/models/post.rb
class Post < ActiveRecord::Base
scope :published, where(:published => true)
end
# app/observers/post_observer.rb
class PostObserver < ActiveRecord::Observer
observe :post
end
# config/application.rb
config.active_record.observers = [:post_observer]
Now, if the posts table doesn't exist yet, whenever you load the
environment you'll get "Could not find table 'posts'". And you
can't migrate because that needs to load the environment, too.
A simple way to recreate this without having to define an
observer is to just do require 'post' somewhere in the environment
or in an initializer.
I don't know much about arel yet but judging from the stack
trace, I think that maybe arel tries to load the table structure
too early. If so, maybe this could be deferred until
evaluation?
I'll try to investigate a bit and see if I can find a solution
for this issue.
In the meantime, here's the relevant bit of the stack trace:
/Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/sqlite_adapter.rb:306:in
table_structure': Could not find table 'posts'
(ActiveRecord::StatementInvalid)
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/connection_adapters/sqlite_adapter.rb:201:in `columns'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/arel-0.2.1/lib/arel/engines/sql/engine.rb:17:in `send'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/arel-0.2.1/lib/arel/engines/sql/engine.rb:17:in `method_missing'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/arel-0.2.1/lib/arel/engines/sql/relations/table.rb:47:in `columns'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/arel-0.2.1/lib/arel/engines/sql/relations/table.rb:25:in `attributes'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/arel-0.2.1/lib/arel/algebra/relations/relation.rb:99:in `find_attribute_matching_name'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/arel-0.2.1/lib/arel/algebra/relations/relation.rb:89:in `[]'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/relation/predicate_builder.rb:23:in `build_from_hash'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/relation/query_methods.rb:185:in `map'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/relation/predicate_builder.rb:9:in `each'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/relation/predicate_builder.rb:9:in `map'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/relation/predicate_builder.rb:9:in `build_from_hash'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/relation/query_methods.rb:191:in `build_where'
from (eval):3:in `where'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/base.rb:561:in `__send__'
from /Users/clemens/.rvm/gems/ruby-1.8.7-p249/gems/activerecord-3.0.0.beta/lib/active_record/base.rb:561:in `where'
from /Users/clemens/tmp/scopes/app/models/post.rb:2