Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL - group by clause or be used in an aggregate function (error)

I'm following this rails cast video: http://railscasts.com/episodes/382-tagging. On Tagging with my Rails 3.2 app on Postgres.

Everything works perfect except for the tag cloud functionality. For some reason the cloud functionality does not work in Production using Heroku.

I get this error

ActionView::Template::Error (PGError: ERROR:  column "tags.id" must appear 

in the GROUP BY clause or be used in an aggregate function

I know the error comes from using Postgres in Heroku, but I have no idea how to fix it. I have posted my code below.

New to Rails....please Help :)

VIEWS

##The error occurs here..

  <div id="tag_cloud">
    <% tag_cloud Dailypost.tag_counts, %w[s m l] do |tag, css_class| %>
      <%= link_to tag.name, tag_path(tag.name), class: css_class %>
    <% end %>
  </div>

MODELS

class Tag < ActiveRecord::Base
  attr_accessible :name
  has_many :taggings
  has_many :dailyposts, through: :taggings
end

class Tagging < ActiveRecord::Base
  attr_accessible :dailypost_id, :tag_id

  belongs_to :tag
  belongs_to :dailypost
end

class Dailypost < ActiveRecord::Base  
  attr_accessible :title, :content, :content_html, :tag_list
  belongs_to :user

  has_many :taggings
  has_many :tags, through: :taggings

  def self.tagged_with(name)
    Tag.find_by_name!(name).dailyposts
  end

  ##I know i have to change the method below, but I do not understand how...Please Help

  def self.tag_counts
    Tag.select("tags.*, count(taggings.tag_id) as count").
      joins(:taggings).group("taggings.tag_id")
  end

  def tag_list
    tags.map(&:name).join(", ")
  end

  def tag_list=(names)
    self.tags = names.split(",").map do |n|
      Tag.where(name: n.strip).first_or_create!
    end
  end

end


class User < ActiveRecord::Base
  attr_accessible :name, :email, :password, :password_confirmation

  has_many :dailyposts, dependent: :destroy

end

SCHEMA

ActiveRecord::Schema.define(:version => 20130728204128) do

  create_table "dailyposts", :force => true do |t|
    t.string   "title"
    t.text     "content"
    t.text     "content_html"
    t.integer  "user_id"
    t.integer  "to_id"
    t.datetime "created_at",         :null => false
    t.datetime "updated_at",         :null => false
    t.string   "photo_file_name"
    t.string   "photo_content_type"
    t.integer  "photo_file_size"
  end

  add_index "dailyposts", ["user_id", "created_at"], :name =>   "index_dailyposts_on_user_id_and_created_at"

  create_table "taggings", :force => true do |t|
    t.integer  "tag_id"
    t.integer  "dailypost_id"
    t.datetime "created_at",   :null => false
    t.datetime "updated_at",   :null => false
  end

  add_index "taggings", ["dailypost_id"], :name => "index_taggings_on_dailypost_id"
  add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"

  create_table "tags", :force => true do |t|
    t.string   "name"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "users", :force => true do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at",                                :null => false
    t.datetime "updated_at",                                :null => false
    t.string   "password_digest"
    t.string   "remember_token"
    t.string   "password_reset_token"
    t.datetime "password_reset_sent_at"
  end

  add_index "users", ["email"], :name => "index_users_on_email", :unique => true
  add_index "users", ["remember_token"], :name => "index_users_on_remember_token"
  add_index "users", ["username"], :name => "index_users_on_username", :unique => true

end
like image 943
Serge Pedroza Avatar asked Feb 16 '23 17:02

Serge Pedroza


1 Answers

This solved my problem :)

Dailypost Model

def self.tag_counts
  Tag.select("tags.id, tags.name,count(taggings.tag_id) as count").
    joins(:taggings).group("taggings.tag_id, tags.id, tags.name")
end    

AplicationHelper

def tag_cloud(tags, classes)
  max = tags.sort_by(&:count).last
  tags.each do |tag|
    index = tag.count.to_f / Integer(max.count) * (classes.size - 1)
    yield(tag, classes[index.round])
  end
end
like image 181
Serge Pedroza Avatar answered Feb 18 '23 05:02

Serge Pedroza