Вставить рубин внутри JavaScript

Я полный новичок в мире RoR.

Хотя я сгенерировал некоторый код, используя rails scaffold. Я также могу опубликовать форму через ajax, используя:remote => true.

И форма публикуется, красиво и чисто! Но я хочу отобразить некоторые данные, которые были возвращены с моего контроллера, используя link_to, чтобы он создал ссылку на маршрут / ресурс.

Я попытался создать файл.js.erb и встроить в него код, но он выдает ошибку:

undefined method `link_to'

код в.js.erb

$(document).ready(function(){


$("#new_post").bind('ajax:success', function(xhr, data, status){ 
    console.log(data)
    if(data.errors){
        console.log("Error!")
    }
    else{
        var user_name = data.user; // json is contained in data variable        
        $("#recent_posts").prepend("<%= j link_to(user_name, '#') %>");
    }
});

});

Куда я иду не так?

1 ответ

Решение

Я думаю, что здесь есть несколько источников ошибок:

undefined method `link_to'

Это очень необычно, так как link_to стандартный помощник вида Вы уверены, что пространство раньше link_to это действительно пробел, а не какой-то другой невидимый символ (иногда вы получаете его, например, в OSX, когда используете space удерживая alt). Кроме того, ваш js erb должен находиться в пространстве имен представления ваших контроллеров, но, поскольку он выполняется при рендеринге действия, похоже, это так.

$(document).ready(function(){

Вам не нужно будет использовать это в .js.erb шаблоны, так как нет готовых событий сработало. jQuery выполняет скрипт сразу же, если DOM все равно готов, так что это не повредит (как правило), это просто не нужно.

$("#new_post").bind('ajax:success', function(xhr, data, status){

Это большая проблема. То, как вы сейчас прикрепляете свой обработчик, он будет прикрепляться каждый раз, когда форма отправляется и сервер возвращает данные. Так что, если есть ошибка, и форма будет отправлена ​​и возвращена во второй раз, у вас будет либо console сообщение или вставка якоря выполняется два раза. Так что лучше быть готовым к такого рода событиям:

$("#new_post").not('.registered').addClass('registered').bind('ajax:success', function(xhr, data, status){

Это предотвратит несколько обработчиков событий.

Тогда есть третья проблема:

var user_name = data.user; // json is contained in data variable        
$("#recent_posts").prepend("<%= j link_to(user_name, '#') %>");

Здесь вы пытаетесь использовать переменную, которую вы назначили в JavaScript в erb встроенный рубин. Это не будет работать, так как переменная ruby user_name оценивается на стороне сервера, когда шаблон отображается. С другой стороны, назначение переменной javascript оценивается в браузере, когда клиент получает отрендеренный шаблон с сервера. Так что ты можешь сделать?

link_to это не все, что волшебство. Он просто отображает тег привязки. Итак, то же самое можно записать так:

var user_name = data.user; // json is contained in data variable        
$("#recent_posts").prepend(["<a href='#'>", user_name, "</a>"].join(''));

Все идет нормально. Однако самая большая проблема, с которой вы столкнулись: сервер не может вернуть оба .js.erb шаблон и json данные сразу. Таким образом, данные, которые вы получите в вашей функции JavaScript, будут просто .js.erb строка шаблона. Связь с сервером в JSON действительно лучшая вещь, так что давайте забудем об интегрированной обработке форм в rails и напишем это сами:

  1. удалять :remote => true из вариантов формы

  2. добавлять :format => :json на ваш create маршрут

    resources :posts, :only => [:create], :format => :json
    resources :posts, :except => [:create]
    
  3. Добавьте javascript в ваши активы, который обрабатывает вашу форму удаленно

    // after DOM ready
    
    var form = $('#new_post');
    form.on('submit', function(e) {
    
      $.ajax({
        url: form.prop('action'),
        type: form.prop('method') || 'POST' //for create action,
        data: form.serializeArray(),
        dataType: form.data('type') || 'json',
        success: function(data, status, xhr) {
              var user_name = data.user; // json is contained in data variable        
              $("#recent_posts").prepend(["<a href='#'>", user_name, "</a>"].join(''));
        },
        error: function(xhr, status, error) {
          console.log('error')
        }
      });
    
      return false; //prevent normal submit
    
    });
    
  4. Теперь вы готовы вернуть чистый JSON с сервера:

    render :json => resource.to_json(:include => :errors)
    
Другие вопросы по тегам