Tagging from Scratch: the Querying Database issue

2019-09-08 03:15发布

问题:

@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.

  • My guess is that is a Query problem to the Posgresql Database.
  • I've got Postgresql correctly installed
  • jQuery-tokenInput is on its place on Application.js //= require jquery.tokeninput
  • Somehow it can load the tags from what was already on the database, but it fails querying the same words dynamically as listed below on pictures.js.coffee code.

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?

回答1:

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 =]



回答2:

Try at your controller:

  @tags = Tag.order(:name)

That's all.