Улучшить ненавязчивый JavaScript (и, возможно, использовать CoffeeScript) в приложении Rails - PullRequest
6 голосов
/ 14 марта 2011

У меня есть приложение, которое использует Javascript для базовых запросов Ajax, таких как автозаполнение и поиск в реальном времени.Например, я реализовал живой поиск следующим образом;Я обнаружил некоторую потенциальную проблему и хотел бы поговорить с вами об этом, чтобы получить лучший код.

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);

Вот вещичто вызывает у меня подозрения по поводу оптимальности моего кода:

  • У меня есть код Javascript в _livesearch_box.html.haml.
  • Даже если я вставлю его в public/javascripts/companies_livesearch.js, мне придется жестко закодировать#search часть в нем.
  • У меня есть #company_list_container (это div, в котором отображается _companies.html.haml), жестко запрограммированный в public/javascripts/companies.js.
  • У меня есть путь /companies/liveseach?query= жестко запрограммирован в public/javascript/companies.js.
  • Я не использую CoffeeScript, главным образом потому, что он ожидает (по крайней мере, если вы используете Barista), чтобы найти где-нибудь чистый код JavaScript (например, в app/coffeescripts/) и компилирует его в public/javascripts.Но в моем приложении у меня также есть файл .js.erb в моем app/views/companies;например, у меня есть система голосования, которая использует следующее в app / views / companies / _vote.js.erb : $("#vote_link_<%= escape_javascript(@company.id.to_s) %>").html("<%= escape_javascript(vote_link_for(@company)) %>") Чтобы заменить ссылку «Проголосовать этой компании» на «Отменить голосование этой компании»один (и наоборот) с Ajax-запросом и отображается действиями vote и unvote в контроллере.Я знаю, что есть Coffee-haml-фильтр, который компилирует CoffeeScript внутри haml-файлов, но это не то, что мне нужно, и его обычно не считают и считают чем-то грязным (?).

Так что вопросыминимум:

  • Как добавить CoffeeScript в мои app/views/*/*.js.*?
  • Должен ли я иметь app/views/*/*.js.* файлов вообще?
  • Как удалить все эти идентификаторы элементови эти пути закодированы в javascripts наиболее эффективным и элегантным способом?

Извините за длинный вопрос, и спасибо за то, что завершили его!

1 Ответ

6 голосов
/ 14 марта 2011

Маршруты

Существуют некоторые решения, такие как js-маршруты (мой форк), которые позволят вам написать Router.post_path(3) в вашем JS / CS.Таким образом, вы можете обойти жесткие URL-адреса.

Смешивание JS и ERB

Я бы посоветовал вам избегать смешивания JS и Ruby.В большинстве случаев вы можете обойти это путем рефакторинга вашего JS-кода, результат будет легче читать и может быть просто перемещен в чистый JS / CS-файл.

# 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)
      # ...

Если вы не совершаете зло,магия, вам даже не понадобится escape_javascript.Но вам придется удалить JavaScript изнутри ваших частичных.jquery.livequery облегчает переход.

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

будет вызываться каждый раз, когда в документ вставляется .company.

Жесткое кодирование DOM-путей

Если выпишем код для конкретного дерева домиков (или специального представления), я не считаю это плохой практикой.Написание ненавязчивого JS похоже на написание CSS - и мы жестко кодируем #company_list_container в CSS, не так ли?

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

Вызов JS-кода из внешнего интерфейса

Чтобы иметь интерфейс междустатические CoffeeScript-файлы и представления, к которым я стремлюсь написать что-то вроде:

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

в конце моих просмотров.Затем будет вызвана функция, которую я написал с CoffeeScript, которая затем улучшит сайт всеми необходимыми сценариями.Возможно, есть более подходящие подходы (например, наличие Rails-подобного маршрутизатора для JavaScript - см. Backbone.js), но это просто и работает для меня.

Также, если мне нужны некоторые данные довольно часто (например, current_user):

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

Однако я не думаю, что существует эффективный способ рефакторинга.Я должен был сделать много рефакторинга, чтобы удалить мой беспорядок ERB / ​​JS.Тем не менее, стоит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...