ruby-on-railspostgresqltaggingacts-as-taggable-onjquery-tokeninput

Tagging from Scratch: the Querying Database issue


@saverio was successful on answer this database query question on Tagging from Scratch: the Tag Cloud Issue

Now I'm trying to connect the tagging system with the jQuery-tokenInput to Create and Find tags dynamically as on http://railscasts.com/episodes/258-token-fields-revised.

Following all the relevant scope:

pictures.js.coffee

jQuery ->
  $('#picture_tag_tokens').tokenInput '/tags.json'
  theme: 'facebook'
  prePopulate: $('#picture_tag_tokens').data('load')

/views/pictures/_form

<div class="field">
  <%= f.label :tag_tokens, "Tags (separated by commas)" %><br />
  <%= f.text_field :tag_tokens, data: {load: @picture.tags} %>
</div>

Here my logic get lost a bit

/models/picture.rb

class Picture < ActiveRecord::Base
  attr_accessible :description, :title, :tag_tokens
  has_many :taggings
  has_many :tags, through: :taggings
  attr_reader :tag_tokens

  #The **below** is the relevant part for the #view/pictures/_form
  def tag_tokens=(tokens)
    self.tag_ids = Tag.ids_from_tokens(tokens)
  end

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

  def self.tag_counts
    Tag.select("tags.*, count(taggings.tag_id) as count").
    joins(:taggings).group("tags.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

Below I could figure out that I'm not being able to query the Database

/models/tag.rb

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

  def self.tokens(query)
    tags = where("name like ?", "%#{query}%")
    if tags.empty?
      [{id: "<<<#{query}>>>", name: "New: \"#{query}\""}]
    else
      tags
    end
  end

  def self.ids_from_tokens(tokens)
    tokens.gsub!(/<<<(.+?)>>>/) { create!(name: $1).id }
    tokens.split(',')
  end
end

And so was how I set my Tags controller behavior

#controllers/tags_controller.rb

class TagsController < ApplicationController
  def index
   @tags = Tag.all
   respond_to do |format|
     format.html
     format.json { render json: @tags.tokens(params[:q]) }
   end
  end
end

So, Why I can't Query the Postgresql and I'm not able to Create or Find Dynamically?


Solution

  • I incorporated a solution that's easy enough: using the Gem ActsAsTaggableOn with jQuery Tokeninput

    If you go through the algorithm below, you will figure out that the question above was just a misconception about the configuration between the Tag System and the jQuery. the following steps will help you in your path:

    1 Put the jQuery Tokeninput files in the right places:

    Vendor > assets > javascripts > jquery-tokeninput.js

    Vendor > assets > stylesheets > token-input-facebook.css (and 2 others)

    2 on the file in apps > assets > javascripts > application.js wright this line before //= require_tree . this make the javascript work

    //= require jquery.tokeninput

    3 on the file in apps > assets > stylesheets > application.css.scss wright before *= require_tree . this make the css work

    *= require token-input-facebook

    4 Put the gem 'acts-as-taggable-on' on your gemfile and run bundle install and the very same steps as here.

    5 make a coustom route in routes.rb for a tag controller index (we are about to define) to enable the json property

    get '/tag.json', to: 'tag#index', as: :pictures_tags

    The Following Code and the above allows us to talke properly to the database

    6 run a rails g tag controller index and on this file wright the following:

    #tag_controller.rb

    def index

         query = params[:q]
         query = query.chomp(" ").downcase
         @tags = ActsAsTaggableOn::Tag.where("tags.name LIKE '%#{query}%' OR tags.name LIKE '#{query}'")
    
    if @tags.empty?
        ActsAsTaggableOn::Tag.find_or_create_by_name_and_id(id: "#{query}", name: "#{query}")
    else 
        respond_to do |format|
            format.html
            format.json { render json: @tags.collect{ |tag| {id: tag.name, name: tag.name } } }
        end
     end            
    

    end

    7 and finally glue everything with the code you will place on app > assets > javascript > your_file_with_tags.js.coffee

    #your_file_with_tags.js.coffee

    jQuery ->

    $('#field_with_tag_list').tokenInput '/tag.json'
    
        theme: 'facebook'
    
        prePopulate: $('#field_with_tag_list').data('load')
    
        preventDuplicates: true
    
        resultsLimit: 3
    
        tokenLimit: 7
    
        tokenDelimiter: ","
    
        searchingText: "hit space for New Tag"
    

    PS: #field_with_tag_list is in your view(usualy _form partial) that you generates to impute the tags like this: (#controller_tag_list) i.e. #pictures_tag_list

    <div class="field">

    `<%= f.label :tag_list %><br />`
    
    `<%= f.text_field :tag_list, data: {load: @picture.tag_list.map {|tag| { id: tag, name: tag }}} %>`
    

    </div>

    All these are experimented code I'm sure that will help you =]