Правильно ли иметь файлы, которые смешивают Javascript и ruby? то есть. (.js.erb)?

недавно я прочитал, что встраивание ruby внутри JavaScript-это не очень хорошая идея. Однако в таких книгах, как гибкая Веб-разработка David Heinemeier Hansson с Rails, это именно то, что она делает. Если вложение ruby с JS не является хорошей идеей, то какова наилучшая практика для такого случая? Учитывая что-то простое, как это: (jQuery + Руби)

posts_controller

def create
  @post = Post.new(params[:post])
    respond_to do |format|
      if @post.save
        format.html { redirect_to(@post, :notice => 'Post was successfully created.') }
        format.js #will use this response to process ajax
      else
        format.html { render :action => "new" }
      end
    end
end

создать.js.Эрб

$tr = $('<tr>');
$td1 = $('<td>').text('<%= @post.title %>');  
$td2 = $('<td>').text('<%= @post.content %>');
$tr.append($td1, $td2);
$('table tbody').append($tr);

каким он должен быть переработан, чтобы следовать "лучшей практике" не врезать руби с JS?(если это так)

мне действительно нужно быть просвещенным в этом, и, возможно, правильно понять концепции, потому что я прочитал, что rails 3.1 полностью отделит JS от Ruby через активы ?(это правильно?)

спасибо !

3 ответов


шаблоны RJS были по существу так, как это делалось в течение длительного времени, поэтому вы все еще видите такую распространенность техники в учебниках. Тем не менее, как вы заметили, они на пути к выходу, и не без причины.

Я уверен, что есть много причин, почему шаблоны RJS очень плохо, но большой - это то, как плотно они соединяют ваш вид JS с вашим представлением HTML. Многие проблемы возникают из-за этого, несколько существо:

  1. отсутствие гибкости.

    используя ваш код в качестве примера. Что делать, если вы хотите иметь возможность создавать сообщения из другого представления? И имеют другой эффект? Может быть, нет <table> на странице вообще, и вы просто хотите, чтобы выскочить сообщение" успех"? Так далее.

    Что делать, если вы просто хотели представление данных ваших сообщений, но ваши шаблоны javascript были написаны для управления HTML?

    как вы справляетесь все это в одном create.js.erb, который тесно связан, скорее всего, в должности new.html.erb шаблон?

  2. сложности.

    шаблоны RJS работают в некотором вакууме. Созданные на стороне сервера, их выполнение не привязано к событиям DOM. Это делает его сложным делать такие вещи, как, скажем, обновить <form> на странице после создания объекта, так как у вас нет системы отсчета для выбора соответствующего <form> в шаблоне JS (например,<form id="new_post_123">). Для этого есть обходные пути, но они более запутаны, чем должны быть.

    путем привязки к стороне клиента формы и работы с результатом эта проблема устраняется. Вам не нужно искать правильную форму для обновления после ответа.

    С, как RJS у вас нет такой привязки, и вы вынуждены использовать известные структуры HTML для извлечения и обработки элементов соответствующий. Один пример ненужного сложность.


что касается вашего вопроса:

мне действительно нужно быть просвещенным в этом, и, возможно, правильно понять концепции, потому что я прочитал, что rails 3.1 полностью отделит JS от Ruby через активы ?(Правильно ли это?)

это по сути верно. Конвейер активов, хотя и прохладный,не предлагает ничего нового. Структуры активов, такие как звездочки и Sass, и рабочие процессы, которые они позволяют, имеют был здесь некоторое время. Конвейер Rails 3.1 asset просто вводит их в стандартную практику. Это скорее вопрос перспективы, как говорил DHH в своем недавнем RailsConf keynote. Привлекая большую организацию к этим активам, в частности, JS-файлы, это заставляет их чувствовать себя более первоклассными гражданами, так сказать, заслуживающими такого же внимания, как ваш внутренний код. В отличие от "мусорного ящика" чувство public/javascripts.


как для реализация:

вы можете сделать что-то вроде этого (хотя непроверенный и немного упрощенный, например, в Rails 3 Вы можете использовать ответчики для этого, а не блок respond_to:

# as you have, but returning the object as data which can be handled client-side,
# rather than RJS generated by the server
def create
  @post = Post.new(params[:post])
  respond_to do |format|
    if @post.save
      format.js { render :json => @post }
    else
      # ...
    end
  end
end

// Then in your client side JS, a handler for your remote form.
$(function(){
  $('#your-create-form').bind('ajax:success', function(data, status, xhr) {
    // simply repeating what you had in the template, replacing the erb with
    // attributes from the returned json
    $tr = $('<tr>');
    $td1 = $('<td>').text(data.title);  
    $td2 = $('<td>').text(data.content);
    $tr.append($td1, $td2);
    $('table tbody').append($tr);
  });
}

Если вы вставляете динамические данные в файлы JavaScript, вам часто приходится давать ему правила кэширования, подходящие для контента, который может часто меняться.

Если вам нужно обрабатывать динамический контент с помощью JS, то обычно лучше иметь статический, кэшируемый, многоразовый скрипт, который получает данные из другого места.

в этом конкретном примере, хотя я не уверен, так как нет большого контекста, похоже, что вам было бы лучше генерировать HTML напрямую, а не создание JS, который генерирует HTML.


Я уверен, что вы можете найти этот вопрос, начиная с PHP разработчик на Perl, ASP и любые другие серверные языки там. Кажется, не так много случаев, когда вы хотели бы иметь свой код javascript inline.. единственный может быть, где вы настраиваете его на определенную ситуацию, но я не могу придумать ни одной ситуации, в которой вам нужно было бы настроить его таким образом.

Peformance-мудрый, если у вас много javascript и вы включите все это в свой вывод, вы раздуете свою страницу. Страница 1k превратится в страницу >100k, если вы добавляете большое приложение. И, наряду с этим, вероятно, будет сложнее кэшировать эту информацию, так как вы, вероятно, настраиваете вывод только немного, если пользователь вошел в систему, или если есть специальное объявление в тот день и т. д. Вам гораздо лучше разделить его на собственный файл, чтобы вы могли "минимизировать" его (http://en.wikipedia.org/wiki/Minification_%28programming%29) также.

от разработчика к разработчику я могу дать вам ужасные истории о том, что javascript (и html) встроены в шаблоны PHP и Smarty. Будьте любезны с тем, с кем вы работаете, и разделите все языки на свои собственные файлы. Предположим, вы работаете с Бобом, и он отличный парень javascript.. но ничего не знает о приложении и о том, как оно выплевывает свой код. Имея на JavaScript smattered в erb будет расстраивать из - за отсутствия единой точки истины для приложения-если он хочет что-то настроить, он будет просматривать все ваши erb, чтобы выяснить, где именно он должен положить его или где он был первоначально. И вы действительно хотите, чтобы кто-то, кто мало знает о структуре вашего бэкэнда, рылся в этих файлах?

есть несколько случаев, хотя, где вы хотели бы поставить загрузки сведения в.. если у вас есть много данных для ввода на страницу при запуске, присвоение этого нескольким переменным при запуске страницы более эффективно, чем выход и выполнение запроса ajax при каждой загрузке страницы.

пожалуйста, будьте добры к нам front-end ребята и если у вас нет реальной веской причины.. держать JS в отдельных файлах :)

Edit: вот пример того, что вы хотите (я думаю), не используя шаблон javascript:

app.js:

postUpdater = function (data) {
    $tr = $('<tr>');
    $td1 = $('<td>').text(data.title);  
    $td2 = $('<td>').text(data.content);
    $tr.append($td1, $td2);
    $('table tbody').append($tr);
};

$("#save_button").click(function () {
    $.post('/save/ur/', {the:data}, postUpdater);
});

в ruby вы захотите просто отобразить @post в json.. Я думаю, что это буквально @post.to_json, но вам, возможно, придется require 'json' для того, чтобы заставить его работать. Это может привести вас туда быстрее, хотя:выход сформировал json с рельсами 3 (Я на самом деле не рубиновый парень.. мы просто используем его в компании, в которой я работаю, поэтому, конечно, я его забираю)

Теперь, что касается теоретического, почему бы просто не вывести шаблонный файл JavaScript. Предположим, у вас есть целая куча вещей, которые должны произойти при сохранении этого файла javascript. Это означает, что вы должны вывести много материала на этот запрос ajax и выполнить его. Вы бы толкнули больший файл через интернет (немного медленнее) и, возможно, должны были бы "оценить" ответ (eval is evil). Так что это плохо. Еще одна, возможно, плохая вещь заключается в том, что вы теряете доступ к тому, откуда вы называли спасение. Итак, если у меня есть это вид..

new PostViewer({
    savePost: function () {
        var self = this;
        $.post('/save/url/', {the:data}, function (response) {
            self.trigger('saveSuccessful', response);
        });
    }
});

когда savePost будет вызван, будет сложнее (без возможного введения многочисленных хаков) просто сказать: "Эй, сохранение было успешным!".

надеюсь, что это немного больше на цели для того, что вы искали.