0

В моем приложении у меня есть уведомления пользователей, где пользователь получает уведомление для определенных действий. Эти уведомления отображаются в раскрывающемся списке на панели навигации (например, Facebook или S.O.). Все уведомления имеют атрибут boolean, называемый: read и по умолчанию установлен в false. Я использую bootstrap с выпадающими списками (в случае, если это помогает).
Я хочу создать метод, когда пользователь щелкает, чтобы открыть раскрывающийся список, все их непрочитанные уведомления становятся считанными.Rails - изменение логического значения по ссылке нажмите

Вот что я до сих пор использовал для метода.

def read_notifications 
    PublicActivity::Activity.where(recipient_id: current_user).where(read: false).update_all(:read => true) 
end 

Это обновление всех уведомлений текущего пользователя: read => true при вызове метода. В представлении вот что я имел до сих пор для выпадающей ссылки.

<%= link_to read_notifications_path, :class => "dropdown-toggle notifications_icon", :'data-toggle' => "dropdown", :controller => "application", :action => "read_notifications", :method => :post do %><% end %> 

и routes.rb У меня было это.

match "/read" => "application#read_notifications", :as => "read_notifications", via: 'post' 

Теперь я знаю, что я не прав, но даже когда я нажимаю на ссылку он делает переключение всех уведомлений пользователя для чтения, он просто действует также в качестве ссылки (Дух) и переходит к другому стр.
Как вы знаете, ссылка на выпадающее меню бутстрапа - «#».

Кто-нибудь знает, как я могу правильно настроить это, когда пользователь нажимает ссылку уведомления в навигационной панели, ВСЕ, что он делает, открывает выпадающий список и изменяет логическое значение на true для всех уведомлений.

Я знаю, что это возможно, я просто еще не смог понять это.
Спасибо, что посмотрели на него.

EDIT

JS файл

$(".notifications_icon").on("click", function(){ 
    $.post("/read", function(data){ 
    $('.notification_badge').text(""); 
    }); 
}); 

Посмотреть

<%= link_to "#", :class => "dropdown-toggle notifications_icon", :'data-toggle' => "dropdown" do %> 
    <span class="notification_badge"><%= find_unread_notifications_count(current_user) %></span> 
<% end %> 

Это Проводка к/чтения, чтобы прочитать все из уведомлений, но не обновляет счетчик

ответ

1

Вам нужна черта ненавязчивый JS. Например, SO имеет класс js-inbox-button, который при нажатии вызывает триггеры обновлений для непрочитанных счетчиков (как для клиента, так и для сервера). Я не буду копаться в источнике JS, но его довольно просто построить.

У вас, похоже, уже есть соответствующий класс (notifications_icon), хотя вы можете использовать что-то еще. Когда клика нажата, используйте jquery $.post.

$(".notifications_icon").on("click", function(){ 
    $.post("/read", function(data){ 
    // remove unread count 
    $('.notification_badge').text(''); 
    }); 
}); 

Теперь это очень простая реализация. Пара предложений:

  1. только делать запросы, когда это необходимо (проверьте непрочитанных счетчика на странице первого)
  2. Используйте атрибут данных по ссылке, чтобы пройти /read путь. Таким образом, вы можете использовать свои помощники пути вместо hardcoding path.
  3. Храните выше JS в отдельном файле (ненавязчивый)
+0

Благодарим за ответ @Damien. –

+1

@ Justin Я бы советовал против другого ответа. Во-первых, это будет делать запрос каждый раз, когда вы нажимаете, и он повторно отображает частичный. Если пользователь отключил JS, он пойдет по пути '/ read', когда они нажмут. Это навязчиво и опирается на негибкий способ управления обратными вызовами JS (с файлами erb.js). Об этом даже говорится в руководствах: http://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript. У вас гораздо больше контроля, если вы извлекаете обработчик вместо простого исправления «remote: true». –

+0

Хорошо. Спасибо за совет! –

1

AJAX.

С помощью добавления remote: true вы начинаете с AJAX. Теперь вызов идет по вашему пути, и ничего не происходит! ура!

Вы хотите, чтобы что-то произошло. Таким образом, в вашем контроллере (я бы не сделать это в application_controller, если бы я тебя ... activities_controller.rb может быть?):

Контроллеры/activities_controller.rb

def read_notifications 
    PublicActivity::Activity.where(recipient_id: current_user).where(read: false).update_all(:read => true) 
    respond_to do |format| 
    format.js 
    end 
end 

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

просмотров/мероприятия/read_notifications.js.erb

$('#your_menu_div').html("<%= j render partial: 'activities/notifications' %>"); 

Теперь вы создаете частичный (views/activities/_notifications.html.erb), который визуализируется в меню выпадающего меню.

Очистить как грязь?

+0

Спасибо @Mallanaga, это работает, но мне нужно дважды щелкнуть ссылку выпадающего списка, чтобы вызвать js, чтобы изменить счет на 0. Выпадающий список открывается одним щелчком мыши, и даже если я нахожусь за пределами раскрывающегося списка, чтобы закрыть box, счетчик не изменяется, пока я не нажму на него снова (всего 2 раза). Weird ??? –

+0

не странно. вы должны внести изменения в свой файл js.erb. Я делаю '('#notifications span.badge'). Html (0) .removeClass ('new');' который устанавливает число в 0 и удаляет класс, который окрашивает значок. – Dudo

+0

Спасибо, да, у меня был код правильный, но переменная find count была в контроллере приложения с before_action, поэтому он не обновлялся. Я переместил его в помощник приложения. –

Смежные вопросы