在轨道

时间:2016-03-13 09:50:07

标签: javascript ruby-on-rails ruby ajax coffeescript

我有一个搜索电影应用程序(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

错误的屏幕截图:

enter image description here

UPD:重新启动Rails之后,AJAX工作正常,但我获得了一倍的​​电影(显示相同的电影),而不是从数据库中获得另外两部电影。

错误从这里(2)开始,也许在这里(1),因为我发送了用户ID,而不是他的最后一部电影ID。

enter image description here

以下是XHR启动时的控制台日志:

enter image description here

如何解决?

P.S。您可以找到此应用here in GitHub,功能分支&#39;加载更多&#39;。

1 个答案:

答案 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的项目。