ruby on rails - Cómo usar jquery-Tokeninput y Acts-as-taggable-on
ruby-on-rails ruby-on-rails-3 (6)
No sé si esto es la totalidad de su error, pero no está llegando a la URL correcta con el complemento tokenInput.
Esta
$("#product_tag_list").tokenInput("/products/tags.json"), {
debiera ser
$("#product_tag_list").tokenInput("/products.json"), {
Como dije, no sé si este es el único problema que tienes, pero si cambias esto, ¿funciona?
EDITAR:
Nunca he usado ActsAsTaggableOn
. ¿Crea un modelo de Tag
para que lo use?
Por lo que se ve en github , si desea consultar todas las etiquetas, es posible que tenga que usar su espacio de nombres en lugar de solo Tag
, lo que significa ActsAsTaggableOn::Tag
. Por ejemplo, puede ver cómo acceden a Tag
s directamente en algunas de las especificaciones .
Así es como utilizas la función autocompletar con jQuery Tokeninput y ActsAsTaggableOn .
En mi situación, estoy usando una forma anidada, pero no debería importar. Todo a continuación es código que funciona.
Código
Modelo del Producto:
attr_accessible :tag_list # i am using the regular :tag_list
acts_as_taggable_on :tags # Tagging products
Controlador de productos:
#1. Define the tags path
#2. Searches ActsAsTaggable::Tag Model look for :name in the created table.
#3. it finds the tags.json path and whats on my form.
#4. it is detecting the attribute which is :name for your tags.
def tags
@tags = ActsAsTaggableOn::Tag.where("tags.name LIKE ?", "%#{params[:q]}%")
respond_to do |format|
format.json { render :json => @tags.map{|t| {:id => t.name, :name => t.name }}}
end
end
Rutas:
# It has to find the tags.json or in my case /products/tags.json
get "products/tags" => "products#tags", :as => :tags
Application.js:
$(function() {
$("#product_tags").tokenInput("/products/tags.json", {
prePopulate: $("#product_tags").data("pre"),
preventDuplicates: true,
noResultsText: "No results, needs to be created.",
animateDropdown: false
});
});
Formar:
<%= p.text_field :tag_list,
:id => "product_tags",
"data-pre" => @product.tags.map(&:attributes).to_json %>
Problema 1 (SOLUCIONADO)
Debe tener la línea:
format.json { render :json => @tags.collect{|t| {:id => t.name, :name => t.name }}}
Nota: también puede usar @tags.map
aquí y no tiene que cambiar el formulario tampoco.
A continuación se encuentran los 2 problemas sobre por qué necesita hacer esto:
Tengo la siguiente Tag
: {"id":1,"name":"Food"}
. Cuando guardo un Product
, etiquetado como "Food"
, debe guardar como ID: 1
cuando busca y encuentra el nombre "Food"
. Actualmente, guarda una nueva Tag
con una nueva identificación que hace referencia al ID de "Food"
, es decir, {"id":19,"name":"1"}
. En su lugar, debería encontrar la ID, mostrar el nombre y hacer un find_or_create_by
para que no cree una nueva Tag
.
Problema 2 (SOLUCIONADO)
Cuando voy a products/show
para ver las etiquetas, hago <%= @product.tag_list %>
. El nombre aparece como " Etiquetas: 1 ", cuando realmente debería ser " Etiquetas: Comida ".
¿Cómo puedo solucionar estos problemas?
Debe definir una ruta en su routes.rb
que debe manejar la ruta de products/tags
. Puedes definirlo así:
get "products/tags" => "products#tags", :as => :tags
Por lo tanto, debería darle un helper tags_path
que debería evaluar a /products/tags
. Esto debería eliminar los errores que mencionaste en la pregunta. Asegúrese de agregar esta ruta antes de definir los resources :product
in your routes.rb
Ahora en actua-como-etiquetable-on , no he usado esta gema, pero deberías mirar el método all_tag_counts
documentación . Su método ProductsController#tags
necesitará algunos cambios en las siguientes líneas. No estoy seguro de si es exactamente lo que se requeriría, ya que uso Mongoid y no puedo probarlo.
def tags
@tags = Product.all_tag_counts.(:conditions => ["#{ActsAsTaggableOn::Tag.table_name}.name LIKE ?", "%#{params[:q]}%"])
respond_to do |format|
format.json { render :json => @tags.collect{|t| {:id => t.name, :name => t.name } }
end
end
pequeño complemento:
Si desea crear las etiquetas sobre la marcha, puede hacer esto en su controlador:
def tags
query = params[:q]
if query[-1,1] == " "
query = query.gsub(" ", "")
Tag.find_or_create_by_name(query)
end
#Do the search in memory for better performance
@tags = ActsAsTaggableOn::Tag.all
@tags = @tags.select { |v| v.name =~ /#{query}/i }
respond_to do |format|
format.json{ render :json => @tags.map(&:attributes) }
end
end
Esto creará la etiqueta, siempre que se golpee la barra espaciadora.
A continuación, puede agregar esta configuración de búsqueda en el script jquery:
noResultsText: ''No result, hit space to create a new tag'',
Está un poco sucio pero funciona para mí.
Tuve problemas para editar las etiquetas si, por ejemplo, el modelo no pudo validar,
Cambié
<%= p.text_field :tag_list,
:id => "product_tags",
"data-pre" => @product.tags.map(&:attributes).to_json %>
a
<%= p.text_field :tag_list,
:id => "product_tags",
"data-pre" => @product.tag_list.map {|tag| {:id => tag, :name => tag } }.to_json %>
Si el formulario no se pudo validar en la primera presentación, estaba creando etiquetas como ID de las etiquetas que había creado en presentaciones posteriores.
Hay un error en el código Application.js. Hay un extra) después de "/products/tags.json". Eliminar el extra). El código debería ser:
$("#product_tags").tokenInput("/products/tags.json", {
prePopulate: $("#product_tags").data("pre"),
preventDuplicates: true,
noResultsText: "No results, needs to be created.",
animateDropdown: false
});
Dos notas: si obtiene las etiquetas modificadas por números en la solicitud POST, use:
tokenValue: "name"
Y si intenta agregar etiquetas que no existen, use (no documentado):
allowFreeTagging: true