Как выполнить вспомогательный метод из JS ERB?
У меня есть вспомогательный метод в моем dashboard_helper.rb
, который выглядит следующим образом:
def show_number_of_comments(node)
if node.comments_count == 1
"#{node.comments_count} Comment"
else
"#{node.comments_count} Comments"
end
end
В моем обычном представлении dashboard#index
я называю это следующим образом:
<h4 class="card-comments-title"><%= show_number_of_comments(node) %></h4>
Но я хотел бы обновить этот обработанный элемент через AJAX всякий раз, когда добавляется новый комментарий, поэтому в моем comment#create.js.erb
я хотел бы ссылаться на этот вспомогательный метод, но когда я его пробую, он не работает:
$('#<%= @card_id %> .card-comments-title').html('<%= show_number_of_comments(@node) %>');
Но когда я это делаю, он работает:
$('#<%= @card_id %> .card-comments-title').html('<%= @comment_count %> Comments');
Проблема с последним заключается в том, что он не обрабатывает плюрализацию.
Какой лучший способ приблизиться к этому?
Изменить 1
Когда я говорю, что это не работает, вот что я имею в виду:
NoMethodError at /nodes/5/comments
==================================
> undefined method `show_number_of_comments' for #<#<Class:0x007fbd3715e5b8>:0x007fbd3715d4d8>
app/views/comments/create.js.erb, line 5
----------------------------------------
Кроме того, объект @node
объявлен в моем Comments#Create
следующим образом:
def create
@node = Node.find(params[:node_id])
@comment = current_user.comments.new(comment_params)
@comment.node = @node
@card_id = params[:card_id]
@comment_count = @node.comments_count + 1
current_user.events.create(action: "commented", eventable: @comment)
binding.pry
respond_to do |format|
if @comment.save and @node.save
format.js
else
format.js
end
end
end
Когда я останавливаю выполнение с помощью binding.pry
, как указано выше, и я пытаюсь сделать @node
, я получаю ожидаемое значение:
[1] pry(#<CommentsController>)> @node
=> #<Node id: 5, name: "Reverse Crunches", family_tree_id: 1, user_id: 1, media_id: 5, media_type: "Video", created_at: "2015-07-25 05:49:51", updated_at: "2015-07-25 21:05:34", circa: nil, is_comment: nil, cached_votes_total: 0, cached_votes_score: 0, cached_votes_up: 0, cached_votes_down: 0, cached_weighted_score: 0, cached_weighted_total: 0, cached_weighted_average: 0.0, cached_user_tag_list: nil, cached_num_user_tags: 0, cached_tagged_user_names: [], comments_count: 3>
Изменить 2
Иногда это просто терпит неудачу. Он не выводит никаких ошибок ни на консоль, ни на мой серверный журнал, она просто заменяет .card-comments-title
пустым значением.
Ответы
Ответ 1
Итак, я понял, что я хотел бы сделать в своем конкретном случае, то есть плюрализировать количество комментариев в моей JS ERB, но я не понял, как использовать helper_method
из моей JS ERB - так что этот ответ doesn На этот вопрос я действительно отвечаю.
Однако я документирую это здесь, если у кого-то есть аналогичная проблема, и мое решение помогает им.
В моем JS ERB все, что я сделал, было использовано методом Rails pluralize. Я полностью забыл об этом, пока не набрал этот вопрос, и он работает как шарм.
Вот фрагмент кода для моего create.js.erb
:
$('#<%= @card_id %> .card-comments-title').html('<%= pluralize(@comment_count, "Comment") %>');
Работает как шарм, но это все еще не отвечает на мой вопрос о ссылках/использовании вспомогательных методов здесь.
Ответ 2
Вы также можете попытаться избежать использования бэкэнд, если не требуется локализация:
var comentsNumber = function(num){
return (num == 0 || num > 1) ? num + " Comments" : num + " Comment"
};
var domObject = $('#<%= @card_id %> .card-comments-title');
В принципе, вы можете легко обновить объект с помощью вызова AJAX и запускать контент для перезагрузки:
var htmlContent = comentsNumber(<%= @comment_count %>);
domObject.html(htmlContent);
Ответ 3
Возможное лучшее решение для отображения сингулярного/множественного текста будет осуществляться через i18n. Вы можете попробовать что-то вроде следующего:
# config/locales/en.yml
en:
comments:
zero: No comments
one: 1 comment
other: %{count} comments
Тогда, на ваш взгляд, вы будете использовать его как:
$('#<%= @card_id %> .card-comments-title').html("<%= t('comments', count: @node.comments_count) %>");
По проблеме с неработающими помощниками: учитывая, что у вас есть dashboard_helper.rb
в каталоге app/helpers/
, ваш помощник должен работать. С проблемой, которую вы описали, где работает следующая строка:
$('#<%= @card_id %> .card-comments-title').html('<%= @comment_count %> Comments');
а следующее:
$('#<%= @card_id %> .card-comments-title').html('<%= show_number_of_comments(@node) %>');
Вы могли бы найти лучший ответ, если бы вы имели выход show_number_of_comments(@node)
, возможно, используя console.log
. Вероятно, этот выход должен быть экранирован с помощью escape_javascript
. Итак, хотя это не конкретное решение, я бы предложил вам попробовать:
$('#<%= @card_id %> .card-comments-title').html('<%= j show_number_of_comments(@node) %>');
Ответ 4
Изменить. Для Rails 3.1+ следующее верно только в том случае, если
config.action_controller.include_all_helpers = false
Ваш DashboardHelper
включен в DashboardController
. Ваш .js.erb
, кажется, принадлежит чем-то вроде CommentsController
.
Вам придется либо переместить ваш вспомогательный метод в ваш ApplictionController
, либо включить помощника, используя helper DashboardHelper
в контроллере, в котором вы хотите его использовать.
Ответ 5
Вы можете попробовать pluralize:
$('#<%= @card_id %> .card-comments-title').html('<%= pluralize(@comment_count, 'Comment') %>');
Он должен работать в обоих местах.
Я пропустил ваше собственное наблюдение.
Я бы предложил переместить помощников, которые вам нужны в нескольких контекстах, в файл application_helper.rb
. Возможно, это не самая лучшая практика, но она будет выполнять эту работу.
Ответ 6
Попробуйте использовать j short для escape_javascript.
$('#<%= @card_id %> .card-comments-title').html('<%= j show_number_of_comments(@node) %>');