Skip to content

Instantly share code, notes, and snippets.

@olistik
Created November 17, 2015 08:28
Show Gist options
  • Save olistik/7096fc58c08c983817eb to your computer and use it in GitHub Desktop.
Save olistik/7096fc58c08c983817eb to your computer and use it in GitHub Desktop.
How to implement (Discussion N:M Tag) with ActiveRecord
class Discussion < ActiveRecord::Base
has_and_belongs_to_many :tags
def self.my_scope
# TODO: replace me with something meaningful
where("discussions.id < 10")
end
def self.tags_count
joins(:tags).
group("tags.id").
order("count_all desc").
count
end
end
discussions = Discussion.my_scope
tags_with_count = TagsForDiscussions.perform(discussions: discussions)
class CreateDiscussions < ActiveRecord::Migration
def change
create_table :discussions do |t|
t.string :name
t.timestamps null: false
end
end
end
class CreateTags < ActiveRecord::Migration
def change
create_table :tags do |t|
t.string :name
t.timestamps null: false
end
end
end
class CreateJoinTableDiscussionsTags < ActiveRecord::Migration
def change
create_join_table :discussions, :tags do |t|
t.index [:discussion_id, :tag_id]
t.index [:tag_id, :discussion_id]
end
end
end
20.times {|index| Discussion.create name: "discussion_#{index}"}
10.times {|index| Tag.create name: "tag_#{index}"}
Discussion.all.sample(10).each do |discussion|
discussion.tag_ids = Tag.all.to_a.sample(5).map(&:id)
end
class Tag < ActiveRecord::Base
has_and_belongs_to_many :discussions
end
module TagsForDiscussions
def self.perform(discussions:)
tags_count = discussions.tags_count
tags_mapping = Tag.
find(tags_count.keys).
each_with_object({}) do |current, memo|
memo[current.id] = current
end
tags_count.map do |tag_id, count|
{
tag: tags_mapping[tag_id],
count: count
}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment