tag rails example and javascript ruby-on-rails dry unobtrusive-javascript coffeescript

example - Mejore la javascript discreta(y posiblemente use CoffeeScript) en una aplicación de Rails



ruby on rails ajax example (1)

Tengo una aplicación que usa Javascript para solicitudes básicas de Ajax, como autocompletado y búsqueda en vivo. Por ejemplo, implementé la búsqueda en vivo de la siguiente manera; Descubrí un problema potencial y me gustaría hablar con usted sobre eso, para tener un mejor código.

app / controllers / company_controller.rb

def livesearch @companies = Company.search(params[:query]) render :partial => "companies", :locals => {:companies => @companies} end

app / views / companies / _companies.html.haml

- if companies.empty? None - else %table#company_list %tr %th Name %th Description %th Products %th = render companies

app / views / companies / _livesearch_box.html.haml

= content_for :scripts, "jlivesearch companies" = form_tag "#", :autocomplete => :off, :remote => true do %span.light Search:   = text_field_tag :search :javascript $(''#search'').livesearch({ searchCallback: update_listed_companies, queryDelay: 200, innerText: "Search companies" });

public / javascripts / companies.js

function update_listed_companies(query) { if(typeof query == "undefined") query = ""; $("#company_list_container").showWith( "/companies/livesearch?query=" + query, false ); }

public / javascripts / application.js

(function($) { $.fn.showWith = function (what, popup) { element = this; $.get(what, function(data) { element.html(data); if(popup) element.bPopup(); }); return element; }; })(jQuery);

Aquí están las cosas que me hacen sospechar sobre la optimalidad de mi código:

  • Tengo un código Javascript en _livesearch_box.html.haml .
  • Incluso si lo coloco en un public/javascripts/companies_livesearch.js tendré que codificar la parte #search en él.
  • Tengo #company_list_container (que es el div en el que se _companies.html.haml ) hardcoded en public/javascripts/companies.js .
  • Tengo la ruta /companies/liveseach?query= hardcoded en public/javascript/companies.js .
  • No estoy usando CoffeeScript, principalmente porque espera (al menos si usa Barista) buscar el código JavaScript puro en alguna parte (por ejemplo, en app/coffeescripts/ ) y lo compila en public/javascripts . Pero en mi aplicación también tengo algún archivo .js.erb en mi app/views/companies ; por ejemplo, tengo un sistema de votación que usa lo siguiente en app / views / companies / _vote.js.erb : $("#vote_link_<%= escape_javascript(@company.id.to_s) %>").html("<%= escape_javascript(vote_link_for(@company)) %>") Reemplazar el enlace" Vote this company "con" Unvote this company "(" No invitar a esta empresa ") con una solicitud de Ajax y se rinde con el vote y la vote unvote acciones en el controlador. Sé que hay coffee-haml-filter que compila CoffeeScript dentro de los archivos haml, pero no es exactamente lo que necesito y generalmente está en desuso y se considera algo sucio (?).

Entonces las preguntas son al menos:

  • ¿Cómo tengo CoffeeScript en mi app/views/*/*.js.* ?
  • ¿Debo tener archivos app/views/*/*.js.* ?
  • ¿Cómo eliminar todos los identificadores de elementos y esas rutas codificadas en javascripts de la manera más eficiente y elegante?

Perdón por la larga pregunta y gracias por llegar al final!


Rutas

Hay algunas soluciones como js-routes (mi fork) que te permitirán escribir Router.post_path(3) en tu JS / CS. De esta forma puede evitar urls de codificación rígida.

Mezcla de JS y ERB

Te aconsejo que evites mezclar JS y Ruby. En la mayoría de los casos puede solucionarlo refacturando su código JS, el resultado será más fácil de leer y simplemente se puede mover a un archivo JS / CS puro.

# based on your vote-link example and assuming that your link # looks like: # # %a(href="#"){:"data-company-id" => @company.id} Vote # => <a href="#" data-company-id="6">Vote</a> makeAllCompaniesVotable: () -> $(''.company a.voteLink'').click -> companyId = $(this).data(''company-id'') $.ajax url: Router.vote_company_path(companyId) # ...

A menos que hagas evil eval-magic, ni siquiera necesitarás escape_javascript . Pero deberá eliminar el JavaScript de sus parciales. jquery.livequery hizo la transición más fácil.

$(`.company`).livequery -> # do something with $(this)

se llamará cada vez que se inserte una .company en el documento.

Hardcoding DOM-Paths

Si está escribiendo código para un dom-tree específico (o una vista específica), no lo consideraría una mala práctica. Escribir JS discreto es como escribir CSS, y también codificamos #company_list_container en CSS, ¿no?

$("#vote_link_<%= escape_javascript(@company.id.to_s) %>") # this is ugly though

Llamar al código JS desde la interfaz

Para tener una interfaz entre los archivos estáticos de CoffeeScript y las vistas, tiendo a escribir algo como:

:javascript $(function(){Companies.index()}); $(function(){Application.globalEnhancements()});

al final de mis puntos de vista. Esto llamará a una función que escribí con CoffeeScript, que luego mejorará el sitio con todos los scripts necesarios. Puede haber mejores enfoques (como tener un enrutador tipo Rails para JavaScript, ver Backbone.js) pero es simple y funciona para mí.

Además, si necesito algunos datos con bastante frecuencia (por ejemplo: el usuario actual):

:javascript window.current_user = #{current_user.to_json};

Sin embargo, no creo que haya una forma eficiente de refactorizar. Tuve que hacer muchas refacciones para eliminar mi ERB / ​​JS mess. Todavía vale la pena, sin embargo.