Ruby on Rails使用Ajax进行渲染

时间:2021-03-20 02:16:59

I am working on a simple website which has posts in forms of songs, now I have implemented like and dislike feature, but when I click on like/dislike it renders the numbers of likes/dislikes on all posts. And when I reload the page it returns them to normal. Now I would like it to change only the numbers for that particular post, without affecting the numbers on other posts?

我正在开发一个简单的网站,其中有歌曲形式的帖子,现在我已经实现了喜欢和不喜欢的功能,但是当我点击喜欢/不喜欢它时会在所有帖子上呈现喜欢/不喜欢的数量。当我重新加载页面时,它将恢复正常。现在我希望它只更改该特定帖子的数字,而不影响其他帖子的数字?

My view for posts:

我对帖子的看法:

<div class="col-6">
    <% for @s in @songs %>
    <div class="card border-secondary mb-1">
        <div class="card-header">
            <div class="col-1">
                <%= image_tag User.find(@s.user_id).user_image.url, :size=>"50x50" %>
            </div>
            <div class="col-11 text-muted">
                <a href="/user/<%= User.find(@s.user_id).username %>" class="info-col">
                    <%= User.find(@s.user_id).username %>                           
                </a> 
                - <%= @s.created_at.to_formatted_s(:short) %>
            </div>
        </div>
        <div class="card-body">
        <h4 class="card-title">
            <a href="<%= song_path(@s) %>" class="link-col"><%= @s.title %></a>
        </h4>
        <p class="card-text"><%= simple_format(@s.content) %></p>
        </div>

        <div class="card-footer text-muted">
            <div class="col-12">
                <div class="row">

                    <div class="col-3" id="song_like">
                        <%= render '/components/song_like' %>
                    </div>

                    <div class="col-3" id="song_dislike">
                        <%= render '/components/song_dislike' %>
                    </div>

                    <div class="col-4" id="song_comment">
                        <%= render '/components/song_comment' %>
                    </div>

                </div>
            </div>
        </div>

    </div>
    <% end %>
</div>

The song_like partial has the following code:

song_like部分具有以下代码:

    <%= link_to like_song_path(@s.id, like: true), remote: true, method: :post do %>
    <i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <span class="songlikes">
        <%= @s.thumbs_up_total %>
    </span>        
<% end %>

The song_dislike partial has the following code:

song_dislike部分具有以下代码:

<%= link_to like_song_path(@s.id, like: false), method: :post, remote: true do %>
    <i class="fa fa-thumbs-o-down fa-lg" aria-hidden="true"></i> &nbsp <span class="songdislikes">
        <%= @s.thumbs_down_total %>
    </span>  
<% end %>

And my 'like' controller is like:

我的'喜欢'控制器就像:

def like
@s = Song.find(params[:id])
@like = Like.create(like: params[:like], user: current_user, song: @s)

respond_to do |format| 
if @like.valid?
    format.html
    format.js
else
    format.html
    format.js
  end
end

end

This is how like.js.erb looks like:

这就是like.js.erb的样子:

    $('.songlikes').html("<%=  @s.thumbs_up_total %>");

$('.songdislikes').html("<%=  @s.thumbs_down_total %>");

Here is the part of routes.rb file:

这是routes.rb文件的一部分:

resources :songs do
  member do
    post 'like'
  end
end

I am assuming there is some issue on rendering or jquery, but can't figure it out. Do You have any instructions?

我假设渲染或jquery存在一些问题,但无法弄明白。你有任何指示吗?

2 个解决方案

#1


0  

EDIT: You should remove the redirect_to in your f.html?

This reloads the page - and the js will therefore not work.

An Ajax call is per definition not reloading the page.

If you remove those lines and try the following:

如果删除这些行并尝试以下操作:


There's no new data in your jQuery.

你的jQuery中没有新数据。

You need a global attribute, so the view can find the data from your controller.

您需要一个全局属性,因此视图可以从控制器中查找数据。

For example:

@like = ...

Then in your view you can add a local to be rendered:

然后在您的视图中,您可以添加要渲染的本地:

$("#song_like").load("<%=j render partial: '/components/song_like', locals: {like: @like} %>");

But, you need to change your partial to be a partial. And change the variable to like so it will be rendered in the right way.

但是,你需要将你的部分改为部分。并将变量更改为类似,以便以正确的方式呈现。

Hope it helps!

希望能帮助到你!

UPDATE

If you want to hit a specific song you can render it with each and then assign an id to your post's class

如果您想要播放特定歌曲,可以使用每个歌曲进行渲染,然后为您的帖子类分配一个ID

For example:

<% @posts.each do |post| %>
  <div class="post-content">
    ... other stuff ...
    <div class="likes like-post-<%= post.id %>">
       .. number of likes
    </div> 
    <%= link_to "Like", link_route_path(post) %>
  </div>
<% end %>


# controller 
# So you can use the id in your js view

@id = params[:id]   

# view.js
$(".like-post-" + "<%= @id %>").html("<%=  @s.thumbs_up_total %>"); 

Hope the idea helps.

希望这个想法有所帮助

#2


0  

change rendering like this:

像这样改变渲染:

<div class="col-3" id="song_like">
 <%= render partial: '/components/song_like', locals: {s: @s, like: true} %>
</div>

then in partial:

部分:

<%= link_to like_song_path(s.id, like: like), method: :post, remote: true do %>
    <i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <%= s.thumbs_up_total %>        
<% end %>

and in controller of like_song

并且在like_song的控制器中

should define

@s= Song.find(params[:id])
like = Like.create(like: params[:like], user: current_user, song: @song)
@like = !like.like # opposite to your current status

rest of the things good and then in like.js.erb

其余的事情好,然后在like.js.erb

$('#songs_like').html("<%= escape_javascript(render partial: '/components/song_like', locals: { s: @s, like: @like } ) %>")

#1


0  

EDIT: You should remove the redirect_to in your f.html?

This reloads the page - and the js will therefore not work.

An Ajax call is per definition not reloading the page.

If you remove those lines and try the following:

如果删除这些行并尝试以下操作:


There's no new data in your jQuery.

你的jQuery中没有新数据。

You need a global attribute, so the view can find the data from your controller.

您需要一个全局属性,因此视图可以从控制器中查找数据。

For example:

@like = ...

Then in your view you can add a local to be rendered:

然后在您的视图中,您可以添加要渲染的本地:

$("#song_like").load("<%=j render partial: '/components/song_like', locals: {like: @like} %>");

But, you need to change your partial to be a partial. And change the variable to like so it will be rendered in the right way.

但是,你需要将你的部分改为部分。并将变量更改为类似,以便以正确的方式呈现。

Hope it helps!

希望能帮助到你!

UPDATE

If you want to hit a specific song you can render it with each and then assign an id to your post's class

如果您想要播放特定歌曲,可以使用每个歌曲进行渲染,然后为您的帖子类分配一个ID

For example:

<% @posts.each do |post| %>
  <div class="post-content">
    ... other stuff ...
    <div class="likes like-post-<%= post.id %>">
       .. number of likes
    </div> 
    <%= link_to "Like", link_route_path(post) %>
  </div>
<% end %>


# controller 
# So you can use the id in your js view

@id = params[:id]   

# view.js
$(".like-post-" + "<%= @id %>").html("<%=  @s.thumbs_up_total %>"); 

Hope the idea helps.

希望这个想法有所帮助

#2


0  

change rendering like this:

像这样改变渲染:

<div class="col-3" id="song_like">
 <%= render partial: '/components/song_like', locals: {s: @s, like: true} %>
</div>

then in partial:

部分:

<%= link_to like_song_path(s.id, like: like), method: :post, remote: true do %>
    <i class="fa fa-thumbs-o-up fa-lg" aria-hidden="true"></i> &nbsp <%= s.thumbs_up_total %>        
<% end %>

and in controller of like_song

并且在like_song的控制器中

should define

@s= Song.find(params[:id])
like = Like.create(like: params[:like], user: current_user, song: @song)
@like = !like.like # opposite to your current status

rest of the things good and then in like.js.erb

其余的事情好,然后在like.js.erb

$('#songs_like').html("<%= escape_javascript(render partial: '/components/song_like', locals: { s: @s, like: @like } ) %>")