0

I have a Ruby app which uses Ramaze and Sequel.

I have the classes Tag and Tagging which have this relationship:

class Tag < Sequel::Model
  one_to_many  :taggings, :class => 'Thoth::Tagging'

class Tagging < Sequel::Model(:taggings)
  many_to_one :tag, :class => 'Thoth::Tag'

I want to return a list of tags in order of popularity, the ones that have the most taggings (filtering out any that have less than three taggings). I'm doing that this way:

tags = .left_outer_join(:taggings, :tag_id => :id).group(:tag_id).having("count(*) > 2").order("count(*) desc").all

This does return what seem to be tag objects, but when I call .id on them, I get the id of a tagging that points to the tag, rather than the tag itself.

On closer inspection, the results are quite different from a regular find:

> tag_regular = Tag[2]
=> #<Thoth::Tag @values={:title=>nil, :position=>nil, :parent_id=>1, :name=>"academic", :id=>2}>

> tag_from_join = Tag.join(:taggings, :tag_id => :id).group(:tag_id).having("count(*) > 2").order("count(*) desc").all.select{|tag| tag.name == "academic"}.first
=> #<Thoth::Tag @values={:tag_id=>2, :post_id=>5, :title=>nil, :position=>nil, :parent_id=>1, :name=>"academic", :id=>1611, :created_at=>nil}>

In both cases I get a Thoth::Tag, but the values are quite different, based on the different fields in the join I suppose.

All I actually need to do is get a list of regular tag objects sorted by the number of taggings, but in an efficient single-query way. Is there a better way?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Max Williams
  • 32,435
  • 31
  • 130
  • 197

1 Answers1

1

The default selection is *, so you are selecting columns from both tags and taggings. If you have an id column in both tables, because Sequel returns records as a hash keyed by column name, columns in the taggings table will override columns with the same name in the tags table.

If you only want the columns from tags, add select_all(:tags) to the dataset.

The Sequel master branch has a table_select plugin that will handle this situation by default.

Jeremy Evans
  • 11,959
  • 27
  • 26