#ruby-on-rails
#ruby-on-rails
Вопрос:
У меня есть приложение rails с почтовым ресурсом, в котором каждая конкретная запись может понравиться / не понравиться.
я хочу иметь возможность ставить лайки / дизлайки без обновления страницы. Я просмотрел несколько других сообщений SO, и все ответы связаны с Coffeescript,, как я могу решить это с помощью vanilla js?
(Я использую Friendly_id и acts_as_votable драгоценные камни)
Контроллер:
class PostsController < ApplicationController
before_action :authenticate_user!, only: [:upvote, :downvote]
before_action :set_post, only: [ :show , :upvote, :downvote]
respond_to :js, :json, :html
def upvote
@post.liked_by current_user
redirect_back(fallback_location: root_path)
end
def downvote
@post.disliked_by current_user
redirect_back(fallback_location: root_path)
end
end
Вид:
<%= link_to like_post_path(@post), class:"like-btn", method: :put, remote: true do %>
<button class="btn btn-warning">
<span><p><i class="fa fa-thumbs-up fa-lg" aria-hidden="true"></i></p></span>
</button>
<% end %>
<%= link_to dislike_post_path(@post), class:"dislike-btn", method: :put, remote: true do %>
<button class="btn btn-warning">
<span><p><i class="fa fa-thumbs-down fa-lg" aria-hidden="true"></i></p></span>
</button>
<% end %>
<span> <%= @post.get_upvotes.size %> </span>
Маршруты:
resources :posts do
member do
put "like" => "posts#upvote"
put "dislike" => "posts#downvote"
end
end
Модели:
class Post < ApplicationRecord
acts_as_votable
extend FriendlyId
friendly_id :title, use: :slugged
end
class User < ApplicationRecord
acts_as_voter
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
пожалуйста, дайте мне знать, если вам нужна какая-либо другая информация, спасибо!
Комментарии:
1. Вы также хотите что-то обновить в представлении после того, как пользователь поддержит или понизит оценку публикации?
2. @sahil да, я хотел бы, чтобы <span> <%= [at]post.get_upvotes.size %> </span> чтобы отразить, что сообщение понравилось / не понравилось
3. Что происходит с кнопкой «Не нравится», когда пользователь нажимает на кнопку «Нравится», она отключена или пользователь все еще может нажать «Отключить», а затем количество «нравится» уменьшается?
4. @sahil вторая вещь.. пользователь все еще может нажимать, и количество нажатий уменьшается. В идеале я хотел бы, чтобы была только одна кнопка, ТОЛЬКО «НРАВИТСЯ». И когда пользователь нажимает, количество увеличивается, меняется стиль или что-то в этом роде, а при повторном нажатии количество уменьшается. По сути, поэтому оно никогда не могло опуститься ниже 0. Но я соглашусь на наличие двух кнопок, если проще
5. @sahil отредактировал сообщение … я не создавал метод, но драгоценный камень acts_as_votable поставляется со встроенной функциональностью.
Ответ №1:
Здесь я использую единственный метод, поскольку вы никогда не хотите, чтобы количество лайков опускалось ниже нуля.
Всякий раз, когда пользователю нравится публикация, количество увеличивается на 1, а цвет значка «большой палец вверх» меняется (просто чтобы показать визуальное изменение).
Когда пользователь нажимает на уже понравившуюся публикацию, количество лайков должно уменьшаться на единицу, поэтому мы должны использовать метод unliked_by, предоставляемый gem.
Для реализации этого мы можем использовать файл upvote.js.erb (помните, что имя файла должно совпадать с именем вашего метода контроллера, это упрощает процесс).
Затем в .js.erb
файле мы можем смешать ruby
с js
и получить желаемый результат, как показано в upvote.js.erb
файле.
Я добавляю дополнительный класс с именем liked
, который изменяет цвет кнопки.
Пожалуйста, обратите внимание: я предполагаю, что у вас есть один пост на странице. Если у вас на странице несколько записей, вам следует добавить идентификаторы в контейнер posts и аналогичным образом изменить js
код в upvote.js.erb
файле.
posts_controller.rb
def upvote
if !current_user.liked? @post
@post.liked_by current_user
elsif current_user.liked? @post
# as the above method can also result nil if he is yet to vote
@post.unliked_by current_user
end
end
просмотры / сообщения / upvote.js.erb
<% if current_user.liked? @post %>
document.getElementsByClassName('like-btn')[0].className = "like-btn liked";
<% else %>
document.getElementsByClassName('like-btn')[0].className = "like-btn";
<% end %>
document.getElementsByClassName('likes-count')[0].innerHTML="<%= @post.get_upvotes.size %>";
просмотр.html.erb
<!-- Adding a class liked -->
<style>
.liked {
color: blue;
}
</style>
<%= link_to like_post_path(@post), class:"like-btn", method: :put, remote: true do %>
<button class="btn btn-warning">
<span><p><i class="fa fa-thumbs-up fa-lg" aria-hidden="true"></i></p></span>
</button>
<% end %>
<span class="likes-count"> <%= @post.get_upvotes.size %> </span>
Комментарии:
1. я этого не пробовал, но должен ли файл vote.js.erb быть с повышенным голосованием.js.erb, чтобы он соответствовал имени действия в контроллере? спасибо, кстати, постараюсь реализовать это сейчас
2. Цвет не меняется, когда нравится, поэтому не уверен, что с этим происходит, но остальное работает. Могу ли я спросить, на что ссылается [0] после getElementByClassName? Большое вам спасибо, это потрясающе
3. Поскольку
getElementsByClassName
метод предоставляет коллекцию всех элементов, имеющих один и тот же класс, нам нужно указать, с каким элементом из коллекции мы хотим работать. В приведенном выше случае мы хотели изменить атрибут первого элемента в коллекции.4. Добавляет ли это класс
liked
к тегу i ?5. на самом деле я только что удалил класс bootstrap btn-warning, потому что, я думаю, он перекрывал пользовательские стили. у меня был этот класс только в качестве теста, после удаления синий цвет отображался нормально