我有一个搜索电影应用程序(Rails 4)和my -movies'第I页我试图在页面加载时显示2个用户电影,然后点击链接后再加载更多'其他2个。
现在我使用此代码获得500(内部服务器错误)。我想我的控制器有问题。我做错了什么?
模型/ user.rb
class User < ActiveRecord::Base
has_many :movies, dependent: :destroy
end
模型/ movie.rb
class Movie < ActiveRecord::Base
belongs_to :user
end
控制器/ users_controller.rb
class UsersController < ApplicationController
before_action :authenticate_user!
after_action :verify_authorized
def my_movies
authorize :user, :my_movies?
if params[:id]
@user_movies = current_user.movies.where('id < ?', params[:id]).limit(2)
else
@user_movies = current_user.movies.limit(2)
end
respond_to do |format|
format.html
format.js
end
end
end
视图/用户/ my_movies.html.slim
.row
.small-12.columns.block.movies_container
= render 'users/user_movies'
.row
.small-12.columns.block.load_more_container
= image_tag 'spinner.svg', style: 'display: none;', class: 'loading_icon'
= link_to 'Load More', my_movies_user_path, class: 'load_more'
视图/用户/ _user_movies.html.slim
- @user_movies.each do |movie|
h2.user_movie data-id='#{movie.id}'
= link_to movie.title, movie_path(movie)
视图/用户/ _user_movies.js.slim
| $('.movies_container').append('
= escape_javascript(render(partial: 'users/user_movies'))
| ');
JS / user.coffee
# when the page is ready for manipulation
$(document).ready ->
# when the load more link is clicked
$('a.load_more').click (e) ->
# prevent the default click action
e.preventDefault()
# hide load more link
$('.load_more').hide()
# show the loading icon
$('.loading_icon').show()
# get the last id and save it in a variable 'last-id'
last_id = $('.user_movie').last().attr('data-id')
# make an ajax call passing along our last users movie id
$.ajax
type: 'GET'
url: $(this).attr('href')
data: id: last_id
dataType: 'script'
success: ->
# hide the loading icon
$('.loading_icon').hide()
# show our load more link
$('.load_more').show()
return
return
return
错误的屏幕截图:
UPD:重新启动Rails之后,AJAX工作正常,但我获得了一倍的电影(显示相同的电影),而不是从数据库中获得另外两部电影。
错误从这里(2)开始,也许在这里(1),因为我发送了用户ID,而不是他的最后一部电影ID。
以下是XHR启动时的控制台日志:
如何解决?
P.S。您可以找到此应用here in GitHub,功能分支&#39;加载更多&#39;。
答案 0 :(得分:0)
首先,我尝试使用 will_paginate gem和无限滚动处理它,但在Chrome&amp;带滚动检测的Firefox(我使用this railscasts技术)。 所以我决定尝试new想法(使用 kaminari gem)并且它完美无缺(请参阅下面的代码),但我想将电影加载为长列表,例如第一个示例通过滚动或点击“加载更多”按钮,无所谓。现在我只有一个按钮,可以在不使用原始分页的情况下通过页面滑动我的电影。也许有人知道如何将它转换为长列表,就像我最初想要的那样?
感谢Dmitriy Nevzorov,他在原帖子的评论中提出了正确的方法。
模型与原帖
相同<强>控制器/ users_controller.rb 强>
class UsersController < ApplicationController
before_action :authenticate_user!
after_action :verify_authorized
def my_movies
authorize :user, :my_movies?
@user_movies = current_user.movies.order('created_at DESC').page(params[:page]).per(5)
end
end
<强>视图/用户/ my_movies.html.slim 强>
.row
.small-12.columns.block.movies_container
= render 'users/user_movies'
- unless @user_movies.current_page == @user_movies.total_pages
.row
.small-12.columns.block
p.view_more
= link_to('View More', url_for(page: @user_movies.current_page + 1))
<强>视图/用户/ my_movies.js.slim 强>
| $('.movies_container').append('#{j render(partial: 'users/user_movies')}');
- if @user_movies.current_page == @user_movies.total_pages
| $('.view-more').remove();
- else
| $('.view-more a').attr('href', '#{url_for(page: @user_movies.current_page + 1)}');
<强>视图/用户/ _user_movies.html.slim 强>
- @user_movies.each do |movie|
h2
= link_to movie.title, movie_path(movie)
<强> JS / my_movies.coffee 强>
$ ->
content = $('.movies_container') # where to load new content
viewMore = $('.view_more') # tag containing the "View More" link
isLoadingNextPage = false # keep from loading two pages at once
lastLoadAt = null # when you loaded the last page
minTimeBetweenPages = 5000 # milliseconds to wait between loading pages
loadNextPageAt = 1000 # pixels above the bottom
waitedLongEnoughBetweenPages = ->
return lastLoadAt == null || new Date() - lastLoadAt > minTimeBetweenPages
approachingBottomOfPage = ->
return document.documentElement.clientHeight +
$(document).scrollTop() < document.body.offsetHeight - loadNextPageAt
nextPage = ->
url = viewMore.find('a').attr('href')
return if isLoadingNextPage || !url
viewMore.addClass('loading')
isLoadingNextPage = true
lastLoadAt = new Date()
$.ajax({
url: url,
method: 'GET',
dataType: 'script',
success: ->
viewMore.removeClass('loading')
isLoadingNextPage = false
lastLoadAt = new Date()
})
# watch the scrollbar
$(window).scroll ->
if approachingBottomOfPage() && waitedLongEnoughBetweenPages()
nextPage()
# failsafe in case the user gets to the bottom
# without infinite scrolling taking affect.
viewMore.find('a').click (e) ->
nextPage()
e.preventDefault()
P.S。更新了GitHub中位于here的项目。