jwood / tenacity

A database client independent way of managing relationships between models backed by different databases.
MIT License
118 stars 17 forks source link

ActiveRecord migrations not working for new models that are the target of an association #31

Closed mattiassvedhem closed 12 years ago

mattiassvedhem commented 12 years ago

Say I have a User model:

class User < ActiveRecord::Base
  include Tenacity
  t_has_many :posts
end

And a post model:

class Post
  include Mongoid::Document
  include Tenacity

  field :title

  t_belongs_to :user
end

If I try to migrate the User model Tenacity will raise an error cause the User table doesn't yet exist.

How would you tackle this?

jwood commented 12 years ago

Hi,

Sorry, but I'm unable to reproduce this error. I created User and Post models with the code you listed. I also created a migration:

class CreateUsers < ActiveRecord::Migration
  def change
    create_table :users do |t|
      t.integer :post_id

      t.timestamps
    end
  end
end

I was able to run the migration, and the users table was created successfully. I tested this using sqlite and mysql.

Here are the versions of the libraries I'm using:

rails 3.1 mongoid 2.2.3 tenacity 0.5.2

What versions of these libraries are you using?

jwood commented 12 years ago

Also, what is the exact error that Tenacity is raising? It may help be track down what is going on.

On a side note, in one day I'll be leaving on vacation. So, if you don't hear back from me, please don't think I'm ignoring you. I'll replay when I return.

mattiassvedhem commented 12 years ago

Hi. Thanks for replying.

Seems to be this relation that is raising the problem, since it's trying to show fields from a non existing table:

t_belongs_to :user

When I try to migrate with:

rake db:migrate
Mysql2::Error: Table 'xxx.users' doesn't exist: SHOW FIELDS FROM `users`

If I uncomment t_belongs_to it works without errors.

mongoid 2.2.3 with rails 3.1

jwood commented 12 years ago

Can you please run rake db:migrate --trace and send me the output?

mattiassvedhem commented 12 years ago
Mysql2::Error: Table 'xxxxx.users' doesn't exist: SHOW FIELDS FROM `users`
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/mysql2_adapter.rb:283:in `query'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/mysql2_adapter.rb:283:in `block in execute'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:244:in `block in log'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activesupport-3.1.1/lib/active_support/notifications/instrumenter.rb:21:in `instrument'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract_adapter.rb:239:in `log'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/mysql2_adapter.rb:283:in `execute'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/mysql2_adapter.rb:473:in `columns'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:95:in `block (2 levels) in initialize'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:185:in `with_connection'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/connection_adapters/abstract/connection_pool.rb:92:in `block in initialize'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/base.rb:712:in `yield'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/base.rb:712:in `default'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/activerecord-3.1.1/lib/active_record/base.rb:712:in `columns'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/tenacity-0.5.2/lib/tenacity/orm_ext/activerecord.rb:52:in `_t_id_type'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/tenacity-0.5.2/lib/tenacity/orm_ext/helpers.rb:9:in `id_class_for'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/tenacity-0.5.2/lib/tenacity/orm_ext/mongoid.rb:94:in `_t_initialize_belongs_to_association'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/tenacity-0.5.2/lib/tenacity/associations/belongs_to.rb:32:in `initialize_belongs_to_association'
/Users/yeggeps/.rbenv/versions/1.9.2-p290/lib/ruby/gems/1.9.1/gems/tenacity-0.5.2/lib/tenacity/class_methods.rb:274:in `t_belongs_to'
jwood commented 12 years ago

OK...I see what's going on here. Tenacity is trying to figure out the type of the primary key so it can setup the proper type in the mongoid document, but it cannot because the table doesn't exist yet. To get around this, in lib/tenacity/orm_ext/activerecord.rb, you can do the following

diff --git a/lib/tenacity/orm_ext/activerecord.rb b/lib/tenacity/orm_ext/activerecord.rb
index 151572f..3322a89 100644
--- a/lib/tenacity/orm_ext/activerecord.rb
+++ b/lib/tenacity/orm_ext/activerecord.rb
@@ -49,7 +49,11 @@ module Tenacity
         include Tenacity::OrmExt::Helpers

         def _t_id_type
-          @_t_id_type_clazz ||= Kernel.const_get(columns.find{ |x| x.primary }.type.to_s.capitalize)
+          @_t_id_type_clazz ||= begin
+                                  Kernel.const_get(columns.find{ |x| x.primary }.type.to_s.capitalize)
+                                rescue
+                                  Integer
+                                end
         end

This will simply default the type to Integer if Tenacity can't figure it out by looking at the table. When I come back from vacation, I'll prepare a proper fix for this, and release a new version of Tenacity.

mattiassvedhem commented 12 years ago

Ah, cool, thanks man! Have a great vacation!

abradner commented 12 years ago

Having also just come across this issue, for the moment I'm just running with a monkey patch until you get a chance to update:

RAILS_ROOT/config/initializers/patch_tenacity_table_missing.rb:

#https://github.com/jwood/tenacity/issues/31
Tenacity::OrmExt::ActiveRecord::ClassMethods.class_eval do
  def _t_id_type
    @_t_id_type_clazz ||= begin
      Kernel.const_get(columns.find { |x| x.primary }.type.to_s.capitalize)
    rescue
      Integer
    end
  end
end

EDIT: missed the leading _ in def _t_id_type

jwood commented 12 years ago

This is fixed in version 0.5.3