ruby on rails - How to only use tag_cloud for current_user? -
in application_controller have this:
def tag_cloud @tags = tag.top_20.sort{ |x,y| x.id <=> y.id } if current_user end
which make tag count work tags users, instead want tag_cloud
show tags of current_user
. tried this:
def tag_cloud @tags = current_user.tags.top_20.sort{ |x,y| x.id <=> y.id } if current_user end
but gave me error:
nomethoderror (undefined method `top_20' #<activerecord::associations::collectionproxy []>): app/controllers/application_controller.rb:13:in `tag_cloud'
even though top_20
defined in tag.rb:
class tag < activerecord::base has_many :taggings scope :top_20, -> { where("taggings_count != 0").order("taggings_count desc").limit(15) } end
i'm using acts-as-taggable-on gem. thank you!
updates
user.rb
class user < activerecord::base acts_as_tagger acts_as_taggable has_many :notifications has_many :activities has_many :activity_likes has_many :liked_activities, through: :activity_likes, class_name: 'activity', source: :liked_activity has_many :liked_comments, through: :comment_likes, class_name: 'comment', source: :liked_comment has_many :valuation_likes has_many :habit_likes has_many :goal_likes has_many :quantified_likes has_many :comment_likes has_many :authentications has_many :habits, dependent: :destroy has_many :levels has_many :combine_tags has_many :valuations, dependent: :destroy has_many :comments has_many :goals, dependent: :destroy has_many :quantifieds, dependent: :destroy has_many :results, through: :quantifieds has_many :notes accepts_nested_attributes_for :habits, :reject_if => :all_blank, :allow_destroy => true accepts_nested_attributes_for :notes, :reject_if => :all_blank, :allow_destroy => true accepts_nested_attributes_for :quantifieds, :reject_if => :all_blank, :allow_destroy => true accepts_nested_attributes_for :results, :reject_if => :all_blank, :allow_destroy => true has_many :active_relationships, class_name: "relationship", foreign_key: "follower_id", dependent: :destroy has_many :passive_relationships, class_name: "relationship", foreign_key: "followed_id", dependent: :destroy has_many :following, through: :active_relationships, source: :followed has_many :followers, through: :passive_relationships, source: :follower attr_accessor :remember_token, :activation_token, :reset_token before_save :downcase_email before_create :create_activation_digest validates :name, presence: true, length: { maximum: 50 } valid_email_regex = /\a[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i validates :email, presence: true, length: { maximum: 255 }, format: { with: valid_email_regex }, uniqueness: { case_sensitive: false }, unless: -> { from_omniauth? } has_secure_password validates :password, length: { minimum: 6 } scope :publish, ->{ where(:conceal => false) } user.tag_counts_on(:tags) def count_mastered @res = habits.reduce(0) |count, habit| habit.current_level == 6 ? count + 1 : count end end def count_challenged @challenged_count = habits.count - @res end def self.from_omniauth(auth) where(provider: auth.provider, uid: auth.uid).first_or_initialize.tap |user| user.provider = auth.provider user.image = auth.info.image user.uid = auth.uid user.name = auth.info.name user.oauth_token = auth.credentials.token user.oauth_expires_at = time.at(auth.credentials.expires_at) user.password = (0...8).map { (65 + rand(26)).chr }.join user.email = (0...8).map { (65 + rand(26)).chr }.join+"@mailinator.com" user.save! end end def self.koala(auth) access_token = auth['token'] facebook = koala::facebook::api.new(access_token) facebook.get_object("me?fields=name,picture") end # returns hash digest of given string. def user.digest(string) cost = activemodel::securepassword.min_cost ? bcrypt::engine::min_cost : bcrypt::engine.cost bcrypt::password.create(string, cost: cost) end # returns random token. def user.new_token securerandom.urlsafe_base64 end # remembers user in database use in persistent sessions. def remember self.remember_token = user.new_token update_attribute(:remember_digest, user.digest(remember_token)) end # forgets user. not sure if remove def forget update_attribute(:remember_digest, nil) end # returns true if given token matches digest. def authenticated?(attribute, token) digest = send("#{attribute}_digest") return false if digest.nil? bcrypt::password.new(digest).is_password?(token) end # activates account. def activate update_attribute(:activated, true) update_attribute(:activated_at, time.zone.now) end # sends activation email. def send_activation_email usermailer.account_activation(self).deliver_now end def create_reset_digest self.reset_token = user.new_token update_attribute(:reset_digest, user.digest(reset_token)) update_attribute(:reset_sent_at, time.zone.now) end # sends password reset email. def send_password_reset_email usermailer.password_reset(self).deliver_now end # returns true if password reset has expired. def password_reset_expired? reset_sent_at < 2.hours.ago end def good_results_count results.good_count end # follows user. def follow(other_user) active_relationships.create(followed_id: other_user.id) end # unfollows user. def unfollow(other_user) active_relationships.find_by(followed_id: other_user.id).destroy end # returns true if current user following other user. def following?(other_user) following.include?(other_user) end private def from_omniauth? provider && uid end # converts email lower-case. def downcase_email self.email = email.downcase unless from_omniauth? end # creates , assigns activation token , digest. def create_activation_digest self.activation_token = user.new_token self.activation_digest = user.digest(activation_token) end end
tags_controller
class tagscontroller < applicationcontroller def index @tags = tag.all end def show @tag = tag.find(params[:id]) end end
routes.rb
get 'tags/:tag', to: 'pages#home', as: :tag
schema.rb
create_table "taggings", force: true |t| t.integer "tag_id" t.integer "taggable_id" t.string "taggable_type" t.integer "tagger_id" t.string "tagger_type" t.string "context", limit: 128 t.datetime "created_at" end add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context" create_table "tags", force: true |t| t.string "name" t.integer "taggings_count", default: 0 end add_index "tags", ["name"], name: "index_tags_on_name", unique: true create_table "users", force: true |t| t.string "name" t.boolean "conceal", default: false t.string "email" t.text "missed_days" t.text "missed_levels" t.string "provider" t.string "uid" t.string "oauth_token" t.datetime "oauth_expires_at" t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "password_digest" t.string "remember_digest" t.boolean "admin", default: false t.string "activation_digest" t.boolean "activated", default: false t.datetime "activated_at" t.string "reset_digest" t.datetime "reset_sent_at" t.string "image" end
goal.rb
class goal < activerecord::base scope :publish, ->{ where(:conceal => false) } belongs_to :user has_many :comments has_many :notifications has_many :notes acts_as_taggable scope :accomplished, -> { where(accomplished: true) } scope :unaccomplished, -> { where(accomplished: false) } scope :private_submit, -> { where(private_submit: true) } scope :public_submit, -> { where(private_submit: false) } validates :name, presence: true has_many :goal_likes has_many :likers, through: :goal_likes, class_name: 'user', source: :liker scope :top_3, -> order("deadline"). limit(3) end end
your issue acts-as-taggable-on
not use tag class. or more specific - works when tags.top_20
since calling on tag class. user#tags
relationship uses actsastaggableon::tag
explains nomethoderror
.
actsastaggableon seems have functionality built in though:
current_user.tags.most_used(20)
addition:
i combining tags several model instances single tag cloud, showing in sidebar.
there nothing in requirement says need create tag
or tagging
class. in fact doing cause , other developers bunch of grief. fact tag cloud on home page works not change fact creating bunch of future issues replacing 2 relatively complex components (tagging , tag classes) tiny stubs willy-nilly.
if @ tag_cloud
implementation pretty easy see takes activerecord::relation or collection or old enumerable such array.
module actsastaggableon module tagshelper # see wiki example using tag_cloud. def tag_cloud(tags, classes) return [] if tags.empty? max_count = tags.sort_by(&:taggings_count).last.taggings_count.to_f tags.each |tag| index = ((tag.taggings_count / max_count) * (classes.size - 1)) yield tag, classes[index.nan? ? 0 : index.round] end end end end
since collections fancy pants versions of arrays merging them easy as:
@tags = foo.tags + bar.tags
however joining relations bit more complex since rails not support sql or clause. (its coming in rails 5). either have load , merge collections above or create own clause arel if multiple sql queries performance issue.
Comments
Post a Comment