Вставить рубин внутри 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 и напишем это сами:
удалять
:remote => true
из вариантов формыдобавлять
:format => :json
на вашcreate
маршрутresources :posts, :only => [:create], :format => :json resources :posts, :except => [:create]
Добавьте 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 });
Теперь вы готовы вернуть чистый
JSON
с сервера:render :json => resource.to_json(:include => :errors)