Skip to content

Instantly share code, notes, and snippets.

@gmodarelli
Last active August 29, 2015 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gmodarelli/564d111b65ac9aee31f4 to your computer and use it in GitHub Desktop.
Save gmodarelli/564d111b65ac9aee31f4 to your computer and use it in GitHub Desktop.
Migrating from a 1-to-many association to a many-to-many association
class Category < ActiveRecord::Base
# Old association
belongs_to :topic
# New association
has_and_belongs_to_many :topics
end
RSpec.describe Category do
...
it 'accepts max 3 topics' do
topics = (1..4).map { |n| FactoryGirl.create :topic, name: "Topic #{n}" }
category = FactoryGirl.build :category, topics: topics
expect(category).not_to be_valid
end
...
end
RSpec.describe Category do
...
it 'accepts max 3 topics' do
topics = (1..4).map { |n| FactoryGirl.create :topic, name: "Topic #{n}" }
category = FactoryGirl.build :category, topics: topics
expect(category).not_to be_valid
expect(category.errors.messages[:topics]).to include("can be a maximum of 3")
end
...
end
class Category < ActiveRecord::Base
# Old association
belongs_to :topic
# New association
has_and_belongs_to_many :topics
validates :topics, length: { maximum: 3 }
end
class Category < ActiveRecord::Base
# Old association
belongs_to :topic
# New association
has_and_belongs_to_many :topics
validates :topics, length: { maximum: 3, message: "can be a maximum of 3" }
end
class CategoriesController < ApplicationController
...
def update
@category = Category.find params[:id]
@category.update_attributes categories_params
end
private
def categories_params
params.require(:category).permit(:name, { topic_ids: [] })
end
end
<%= form_for(@category) do |f| %>
...
<%= f.collection_select :topic_ids, Topic.all, :id, :name, { }, { include_blank: false, multiple: true } %>
...
<% end %>
value_length = value.respond_to?(:length) ? value.length : value.to_s.length
class CreateTopicsListsAssociation < ActiveRecord::Migration
def change
create_table :categories_topics, id: false do |t|
t.belongs_to :category, index: true
t.belongs_to :topic, index: true
end
end
end
desc 'Migrate to many-to-many categories topics associations'
task 'topics:migrate_associations' => :environment do
Category.where.not(topic_id: nil).each do |category|
topic = category.topic
category.topics = [topic]
category.topic = nil
category.save!
end
end
class Topic < ActiveRecord::Base
# Old association
# has_many :categories
# New association
has_and_belongs_to_many :categories
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment