I had a lot of issues getting this to work, but through a lot of parsing the Rails server error messages and a database client, I was able to massage this into working. Here is what I did:
With Rails 4, the association can be created with the has_and_belongs_to_many relationship in the models and with create_join_table in a separate migration. Of course, using the rails generators fall short of our goal. Also note that create_join_table works differently and may not even be available in previous versions of Rails.
Step 1. Generate a migration for the join table without the namespaces. We'll adjust it later.
$ rails g migration CreateModelAModelBJoinTable model_a model_b
# db/migrate/<somenumbers>_create_model_a_model_b_join_table.rb
class CreateModelAModelBJoinTable < ActiveRecord::Migration
def change
create_join_table :model_as, :model_bs do |t|
# t.index [:model_a_id, :model_b_id]
# t.index [:model_b_id, :model_a_id]
end
end
end
The migration will need some massaging. We'll need to:
- Override the table name to account for namespaces
- Optionally, select an index. Tip: If your namespaces and model names are long, you may have to override the index name if it goes over the character limit imposed by your database.
Here's the final join table migration, noting the inclusion of the namespaces in the table name, but excluding the namespace in the indices. Simply, this will name the table and its indices the way that rails has_and_belongs_to_many will expect.
# db/migrate/<somenumbers>_create_model_a_model_b_join_table.rb
class CreateModelAModelBJoinTable < ActiveRecord::Migration
def change
create_join_table :model_as, :model_bs, table_name: :namespace_model_as_namespace_model_bs do |t|
t.index [:model_a_id, :model_b_id], name: :index_namespace_model_ab # or whatever, according to your database naming scheme
# t.index [:model_b_id, :model_a_id]
end
end
end
Step 2. Set up our models with the has_and_belongs_to_many associations.
In addition to the association, we need to override the class name and join table name.
# app/models/namespace/model_a.rb
class Namespace::ModelA < ActiveRecord::Base
has_and_belongs_to_many :namespace_model_b, class_name: "Namespace:ModelB", join_table: "namespace_model_as_namespace_model_bs"
end
Step 3. Run the database migrations
rake db:migrate
Final tips if you encounter issues:
You can always back out a migration, delete it, and start over as such:
$ rake db:rollback STEP=1
$ rails d migration CreateModelAModelBJoinTable
Hope this helps!