использование ajax для acts_as_voteable в рельсах - PullRequest
0 голосов
/ 02 октября 2018

я пытаюсь использовать ajax в gem_s действие_as_votable, чтобы страница не обновлялась при голосовании / повышении.Я добавил для этого методы контроллера и добавил удаленные значения true в ссылки.Однако я думаю, что остались только два файла .js.erb.Я огляделся здесь и нашел документацию по ruby, и я не могу найти, как это сделать для этого случая.спасибо

VM23182:1 Uncaught ReferenceError: $ is not defined
    at <anonymous>:1:1
    at processResponse (application-50000f29e1bf2752ae7e56dda39f10dd0f67a47aea5c3f07ed0d933f3e1a256a.js:268)
    at application-50000f29e1bf2752ae7e56dda39f10dd0f67a47aea5c3f07ed0d933f3e1a256a.js:196
    at XMLHttpRequest.xhr.onreadystatechange (application-50000f29e1bf2752ae7e56dda39f10dd0f67a47aea5c3f07ed0d933f3e1a256a.js:251)

`$('.unlike_post').bind('ajax:success', function(){
   $(this).parent().parent().find('.vote_count').html('<%= escape_javascript @post.votes_for.size.to_s %>');
   $(this).closest('.unlike_post').hide();
   $(this).closest('.votes').html(' <%= link_to "Like", like_post_path(@post), remote: true, method: :get, class: "like_post" %>');

});`

Started PUT "/tweets/60/like" for 127.0.0.1 at 2018-10-02 00:06:40 +0100
Processing by TweetsController#upvote as JS
  Parameters: {"id"=>"60"}
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["id", 3], ["LIMIT", 1]]
  ↳ /Users/benherring/.rbenv/versions/2.4.4/lib/ruby/gems/2.4.0/gems/activerecord-5.2.1/lib/active_record/log_subscriber.rb:98
  Tweet Load (0.2ms)  SELECT  "tweets".* FROM "tweets" WHERE "tweets"."id" = $1 LIMIT $2  [["id", 60], ["LIMIT", 1]]
  ↳ app/controllers/tweets_controller.rb:57
   (0.4ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" = $1 AND "votes"."votable_type" = $2 AND "votes"."voter_id" = $3 AND "votes"."vote_scope" IS NULL AND "votes"."voter_type" = $4  [["votable_id", 60], ["votable_type", "Tweet"], ["voter_id", 3], ["voter_type", "User"]]
  ↳ app/controllers/tweets_controller.rb:58
  ActsAsVotable::Vote Load (0.6ms)  SELECT  "votes".* FROM "votes" WHERE "votes"."votable_id" = $1 AND "votes"."votable_type" = $2 AND "votes"."voter_id" = $3 AND "votes"."vote_scope" IS NULL AND "votes"."voter_type" = $4 ORDER BY "votes"."id" DESC LIMIT $5  [["votable_id", 60], ["votable_type", "Tweet"], ["voter_id", 3], ["voter_type", "User"], ["LIMIT", 1]]
  ↳ app/controllers/tweets_controller.rb:58
   (0.2ms)  BEGIN
  ↳ app/controllers/tweets_controller.rb:58
  ActsAsVotable::Vote Update (0.5ms)  UPDATE "votes" SET "updated_at" = $1, "vote_flag" = $2 WHERE "votes"."id" = $3  [["updated_at", "2018-10-01 23:06:40.357671"], ["vote_flag", true], ["id", 10]]
  ↳ app/controllers/tweets_controller.rb:58
   (1.3ms)  COMMIT
  ↳ app/controllers/tweets_controller.rb:58
  Rendering tweets/vote.js.erb
   (0.4ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" = $1 AND "votes"."votable_type" = $2 AND "votes"."vote_flag" = $3  [["votable_id", 60], ["votable_type", "Tweet"], ["vote_flag", true]]
  ↳ app/views/tweets/_icons.html.erb:5
   (0.6ms)  SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" = $1 AND "votes"."votable_type" = $2 AND "votes"."vote_flag" = $3  [["votable_id", 60], ["votable_type", "Tweet"], ["vote_flag", false]]
  ↳ app/views/tweets/_icons.html.erb:9
  Rendered tweets/_icons.html.erb (5.7ms)
  Rendered tweets/vote.js.erb (8.7ms)
Completed 200 OK in 40ms (Views: 21.0ms | ActiveRecord: 4.7ms)

resources :tweets do
  member do
    put "like", to: "tweets#upvote"
    put "dislike", to: "tweets#downvote"
  end

<div id="tweets">
  <% @tweets.each do |tweet|  %>
  <div class="card">

    <h4 class = "username"><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
    <p class="tweet-content"><%= tweet.content %></p>
    <p class="date"><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
    <div class="icons">

      <%= link_to like_tweet_path(tweet),remote: true , method: :put do %>
      <div class="upvote"><i class="fas fa-thumbs-up"></i> <%= tweet.get_upvotes.size %></div>
      <% end %>
      <%= link_to dislike_tweet_path(tweet), remote: true, method: :put do %>
      <div><i class="fas fa-thumbs-down"></i> <%= tweet.get_downvotes.size %></div>
      <% end %>
    </div>
  </div>
 <% end %>
</div>

  def upvote
  @tweet = Tweet.find(params[:id])
  @tweet.upvote_by current_user
  respond_to do |format|
    format.html {redirect_to :tweets}
    format.js {render layout: false}
    # redirect_to :tweets
  # redirect_to :tweets
  #  if request.xhr?
  #   head :ok
  # else
  end
end

def downvote
  @tweet = Tweet.find(params[:id])
  @tweet.downvote_by current_user
  respond_to do |format|
    format.html {redirect_to :tweets}
    format.js {render layout: false}
  # redirect_to :tweets
end
end

1 Ответ

0 голосов
/ 02 октября 2018

Похоже, что вы изначально начали использовать привязку обработчиков к кнопкам, которые прослушивают успешные запросы.Это справедливый способ сделать это, но - поскольку вы уже используете Rails UJS - возможно, существует "лучший" способ.

В Rails UJS файлы JS, возвращаемые из удаленного действия, автоматически выполняются.На мой взгляд, более идиоматический способ Rails сделать это следующим образом:

Извлеките иконки в их собственный шаблон:

<div id="tweets">
  <% @tweets.each do |tweet|  %>
  <div id="tweet-<%= tweet.id %>" class="card">

    <h4 class = "username"><%= link_to tweet.user.username, user_path(tweet.user) %></h4>
    <p class="tweet-content"><%= tweet.content %></p>
    <p class="date"><%= tweet.created_at.strftime("%B %d %Y, %l:%M%P") %></p>
    <%= render 'icons', tweet: tweet %>
  </div>
 <% end %>
</div>

tweets/_icons.html.erb:

<div class="icons">
  <%= link_to like_tweet_path(tweet),remote: true , method: :put do %>
    <div class="upvote"><i class="fas fa-thumbs-up"></i> <%= tweet.get_upvotes.size %></div>
  <% end %>

  <%= link_to dislike_tweet_path(tweet), remote: true, method: :put do %>
    <div class="downvote"><i class="fas fa-thumbs-down"></i> <%= tweet.get_downvotes.size %></div>
  <% end %>
</div>

Затем в действиях контроллера upvote / downvote вы бы format.js { render 'vote' } жили бы на tweets/vote.js.erb и выглядели бы так:

document.querySelector('#tweet-<%= @tweet.id %> .icons').outerHTML = '<%= j render('icons', tweet: @tweet) %>';

Теперь вы можете изменять tweets/_icons.html.erb для обеспечения дополнительной функциональности (например, визуальная обратная связь по голосам или изменение URL-адресов ссылок, чтобы отменить голос).


Старый метод jQuery

Сохранение этого "старого" метода jQuery дляте люди, которые сталкиваются с подобной проблемой и используют jQuery.Хотя, действительно, вам, вероятно, это не нужно .

$('#tweet-<%= @tweet.id %> .icons').replaceWith('<%= j render('icons', tweet: @tweet) %>');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...