Use cursored pagination, remove WillPaginate
This commit is contained in:
parent
c292f51957
commit
101b3b68d3
2
Gemfile
2
Gemfile
|
@ -22,8 +22,6 @@ gem 'haml', '~> 5.0'
|
||||||
gem 'bootstrap-sass', '~> 3.4.0'
|
gem 'bootstrap-sass', '~> 3.4.0'
|
||||||
gem 'bootswatch-rails'
|
gem 'bootswatch-rails'
|
||||||
gem 'sweetalert-rails'
|
gem 'sweetalert-rails'
|
||||||
gem 'will_paginate'
|
|
||||||
gem 'will_paginate-bootstrap'
|
|
||||||
gem 'devise', '~> 4.0'
|
gem 'devise', '~> 4.0'
|
||||||
gem 'devise-i18n'
|
gem 'devise-i18n'
|
||||||
gem 'devise-async'
|
gem 'devise-async'
|
||||||
|
|
|
@ -499,9 +499,6 @@ GEM
|
||||||
websocket-driver (0.7.1)
|
websocket-driver (0.7.1)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.4)
|
websocket-extensions (0.1.4)
|
||||||
will_paginate (3.3.0)
|
|
||||||
will_paginate-bootstrap (1.0.2)
|
|
||||||
will_paginate (>= 3.0.3)
|
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
|
|
||||||
|
@ -584,8 +581,6 @@ DEPENDENCIES
|
||||||
uglifier (>= 1.3.0)
|
uglifier (>= 1.3.0)
|
||||||
unicorn
|
unicorn
|
||||||
web-console (< 4.0.0)
|
web-console (< 4.0.0)
|
||||||
will_paginate
|
|
||||||
will_paginate-bootstrap
|
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.1.4
|
2.1.4
|
||||||
|
|
|
@ -3,6 +3,13 @@ class GroupController < ApplicationController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@group = current_user.groups.find_by_name!(params[:group_name])
|
@group = current_user.groups.find_by_name!(params[:group_name])
|
||||||
@timeline = @group.timeline.paginate(page: params[:page])
|
@timeline = @group.cursored_timeline(last_id: params[:last_id])
|
||||||
|
@timeline_last_id = @timeline.map(&:id).min
|
||||||
|
@more_data_available = !@group.cursored_timeline(last_id: @timeline_last_id, size: 1).count.zero?
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html
|
||||||
|
format.js
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,28 +2,37 @@ class InboxController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@inbox = Inbox.where(user: current_user)
|
@inbox = current_user.cursored_inbox(last_id: params[:last_id])
|
||||||
.order(:created_at).reverse_order
|
@inbox_last_id = @inbox.map(&:id).min
|
||||||
.paginate(page: params[:page])
|
@more_data_available = !current_user.cursored_inbox(last_id: @inbox_last_id, size: 1).count.zero?
|
||||||
@inbox_count = Inbox.where(user: current_user).count
|
@inbox_count = current_user.inboxes.count
|
||||||
|
|
||||||
if params[:author].present?
|
if params[:author].present?
|
||||||
begin
|
begin
|
||||||
@author = true
|
@author = true
|
||||||
@target_user = User.where('LOWER(screen_name) = ?', params[:author].downcase).first!
|
@target_user = User.where('LOWER(screen_name) = ?', params[:author].downcase).first!
|
||||||
@inbox_author = current_user.inboxes.joins(:question)
|
@inbox_author = @inbox.joins(:question)
|
||||||
.where(questions: { user_id: @target_user.id, author_is_anonymous: false })
|
.where(questions: { user_id: @target_user.id, author_is_anonymous: false })
|
||||||
.paginate(page: params[:page])
|
@inbox_author_count = current_user.inboxes
|
||||||
@inbox_author_count = current_user.inboxes.joins(:question)
|
.joins(:question)
|
||||||
.where(questions: { user_id: @target_user.id, author_is_anonymous: false })
|
.where(questions: { user_id: @target_user.id, author_is_anonymous: false })
|
||||||
.count
|
.count
|
||||||
|
|
||||||
if @inbox_author.empty?
|
if @inbox_author.empty?
|
||||||
@empty = true
|
@empty = true
|
||||||
flash.now[:info] = "No questions from @#{params[:author]} found, showing default entries instead!"
|
flash.now[:info] = "No questions from @#{params[:author]} found, showing default entries instead!"
|
||||||
else
|
else
|
||||||
@inbox = @inbox_author
|
@inbox = @inbox_author
|
||||||
@inbox_count = @inbox_author_count
|
@inbox_count = @inbox_author_count
|
||||||
|
@inbox_last_id = @inbox.map(&:id).min
|
||||||
|
@more_data_available = !current_user.cursored_inbox(last_id: @inbox_last_id, size: 1)
|
||||||
|
.joins(:question)
|
||||||
|
.where(questions: { user_id: @target_user.id, author_is_anonymous: false })
|
||||||
|
.count
|
||||||
|
.zero?
|
||||||
end
|
end
|
||||||
rescue
|
rescue => e
|
||||||
|
NewRelic::Agent.notice_error(e)
|
||||||
flash.now[:error] = "No user with the name @#{params[:author]} found, showing default entries instead!"
|
flash.now[:error] = "No user with the name @#{params[:author]} found, showing default entries instead!"
|
||||||
@not_found = true
|
@not_found = true
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,16 +3,28 @@ class NotificationsController < ApplicationController
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@type = params[:type]
|
@type = params[:type]
|
||||||
@notifications = if @type == 'all'
|
@notifications = cursored_notifications_for(type: @type, last_id: params[:last_id])
|
||||||
Notification.for(current_user)
|
@notifications_last_id = @notifications.map(&:id).min
|
||||||
elsif @type == 'new'
|
@more_data_available = !cursored_notifications_for(type: @type, last_id: @notifications_last_id, size: 1).count.zero?
|
||||||
Notification.for(current_user).where(new: true)
|
|
||||||
else
|
|
||||||
Notification.for(current_user).where('LOWER(target_type) = ?', @type)
|
|
||||||
end.paginate(page: params[:page])
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js
|
format.js
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def cursored_notifications_for(type:, last_id:, size: nil)
|
||||||
|
cursor_params = { last_id: last_id, size: size }.compact
|
||||||
|
|
||||||
|
case type
|
||||||
|
when 'all'
|
||||||
|
Notification.cursored_for(current_user, **cursor_params)
|
||||||
|
when 'new'
|
||||||
|
Notification.cursored_for(current_user, new: true, **cursor_params)
|
||||||
|
else
|
||||||
|
Notification.cursored_for_type(current_user, type, **cursor_params)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,7 +2,10 @@ class PublicController < ApplicationController
|
||||||
before_action :authenticate_user!
|
before_action :authenticate_user!
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@timeline = Answer.joins(:user).where(users: { privacy_allow_public_timeline: true }).all.reverse_order.paginate(page: params[:page])
|
@timeline = Answer.cursored_public_timeline(last_id: params[:last_id])
|
||||||
|
@timeline_last_id = @timeline.map(&:id).min
|
||||||
|
@more_data_available = !Answer.cursored_public_timeline(last_id: @timeline_last_id, size: 1).count.zero?
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js
|
format.js
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
class QuestionController < ApplicationController
|
class QuestionController < ApplicationController
|
||||||
def show
|
def show
|
||||||
@question = Question.find(params[:id])
|
@question = Question.find(params[:id])
|
||||||
@answers = @question.answers.reverse_order.paginate(page: params[:page])
|
@answers = @question.cursored_answers(last_id: params[:last_id])
|
||||||
|
@answers_last_id = @answers.map(&:id).min
|
||||||
|
@more_data_available = !@question.cursored_answers(last_id: @answers_last_id, size: 1).count.zero?
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js
|
format.js
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class StaticController < ApplicationController
|
class StaticController < ApplicationController
|
||||||
def index
|
def index
|
||||||
if user_signed_in?
|
if user_signed_in?
|
||||||
@timeline = current_user.timeline.paginate(page: params[:page])
|
@timeline = current_user.cursored_timeline(last_id: params[:last_id])
|
||||||
|
@timeline_last_id = @timeline.map(&:id).min
|
||||||
|
@more_data_available = !current_user.cursored_timeline(last_id: @timeline_last_id, size: 1).count.zero?
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.js
|
format.js
|
||||||
|
|
|
@ -5,7 +5,9 @@ class UserController < ApplicationController
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||||
@answers = @user.answers.reverse_order.paginate(page: params[:page])
|
@answers = @user.cursored_answers(last_id: params[:last_id])
|
||||||
|
@answers_last_id = @answers.map(&:id).min
|
||||||
|
@more_data_available = !@user.cursored_answers(last_id: @answers_last_id, size: 1).count.zero?
|
||||||
|
|
||||||
if user_signed_in?
|
if user_signed_in?
|
||||||
notif = Notification.where(target_type: "Relationship", target_id: @user.active_relationships.where(target_id: current_user.id).pluck(:id), recipient_id: current_user.id, new: true).first
|
notif = Notification.where(target_type: "Relationship", target_id: @user.active_relationships.where(target_id: current_user.id).pluck(:id), recipient_id: current_user.id, new: true).first
|
||||||
|
@ -72,7 +74,9 @@ class UserController < ApplicationController
|
||||||
def followers
|
def followers
|
||||||
@title = 'Followers'
|
@title = 'Followers'
|
||||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||||
@users = @user.followers.reverse_order.paginate(page: params[:page])
|
@users = @user.cursored_followers(last_id: params[:last_id])
|
||||||
|
@users_last_id = @users.map(&:id).min
|
||||||
|
@more_data_available = !@user.cursored_followers(last_id: @users_last_id, size: 1).count.zero?
|
||||||
@type = :friend
|
@type = :friend
|
||||||
render 'show_follow'
|
render 'show_follow'
|
||||||
end
|
end
|
||||||
|
@ -80,7 +84,9 @@ class UserController < ApplicationController
|
||||||
def friends
|
def friends
|
||||||
@title = 'Following'
|
@title = 'Following'
|
||||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||||
@users = @user.friends.reverse_order.paginate(page: params[:page])
|
@users = @user.cursored_friends(last_id: params[:last_id])
|
||||||
|
@users_last_id = @users.map(&:id).min
|
||||||
|
@more_data_available = !@user.cursored_friends(last_id: @users_last_id, size: 1).count.zero?
|
||||||
@type = :friend
|
@type = :friend
|
||||||
render 'show_follow'
|
render 'show_follow'
|
||||||
end
|
end
|
||||||
|
@ -88,7 +94,9 @@ class UserController < ApplicationController
|
||||||
def questions
|
def questions
|
||||||
@title = 'Questions'
|
@title = 'Questions'
|
||||||
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
@user = User.where('LOWER(screen_name) = ?', params[:username].downcase).first!
|
||||||
@questions = @user.questions.where(author_is_anonymous: false).reverse_order.paginate(page: params[:page])
|
@questions = @user.cursored_questions(last_id: params[:last_id])
|
||||||
|
@questions_last_id = @questions.map(&:id).min
|
||||||
|
@more_data_available = !@user.cursored_questions(last_id: @questions_last_id, size: 1).count.zero?
|
||||||
end
|
end
|
||||||
|
|
||||||
def data
|
def data
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class Answer < ApplicationRecord
|
class Answer < ApplicationRecord
|
||||||
|
extend Answer::TimelineMethods
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :question
|
belongs_to :question
|
||||||
has_many :comments, dependent: :destroy
|
has_many :comments, dependent: :destroy
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Answer::TimelineMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_public_timeline, :public_timeline
|
||||||
|
|
||||||
|
def public_timeline
|
||||||
|
joins(:user)
|
||||||
|
.where(users: { privacy_allow_public_timeline: true })
|
||||||
|
.order(:created_at)
|
||||||
|
.reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,38 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module CursorPaginatable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
# Defines a cursor paginator.
|
||||||
|
#
|
||||||
|
# This method will define a new method +name+, which accepts the keyword
|
||||||
|
# arguments +last_id+ for defining the last id the cursor will operate on,
|
||||||
|
# and +size+ for the amount of records it should return.
|
||||||
|
#
|
||||||
|
# @param name [Symbol] The name of the method for the cursor paginator
|
||||||
|
# @param scope [Symbol] The name of the method which returns an
|
||||||
|
# ActiveRecord scope.
|
||||||
|
#
|
||||||
|
# @example
|
||||||
|
# class User
|
||||||
|
# has_many :answers
|
||||||
|
#
|
||||||
|
# include CursorPaginatable
|
||||||
|
# define_cursor_paginator :cursored_answers, :recent_answers
|
||||||
|
#
|
||||||
|
# def recent_answers
|
||||||
|
# self.answers.order(:created_at).reverse_order
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
def define_cursor_paginator(name, scope, default_size: APP_CONFIG.fetch('items_per_page'))
|
||||||
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
||||||
|
def #{name}(*args, last_id: nil, size: #{default_size}, **kwargs)
|
||||||
|
s = self.#{scope}(*args, **kwargs).limit(size)
|
||||||
|
s = s.where(s.arel_table[:id].lt(last_id)) if last_id.present?
|
||||||
|
s
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,8 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class Group < ApplicationRecord
|
class Group < ApplicationRecord
|
||||||
|
include Group::TimelineMethods
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :group_members, dependent: :destroy
|
has_many :group_members, dependent: :destroy
|
||||||
|
|
||||||
|
@ -22,9 +24,4 @@ class Group < ApplicationRecord
|
||||||
def remove_member(user)
|
def remove_member(user)
|
||||||
GroupMember.where(group: self, user: user).first!.destroy
|
GroupMember.where(group: self, user: user).first!.destroy
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Array] the groups' timeline
|
|
||||||
def timeline
|
|
||||||
Answer.where("user_id in (?)", members.pluck(:user_id)).order(:created_at).reverse_order
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Group::TimelineMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_timeline, :timeline
|
||||||
|
|
||||||
|
# @return [Array] the groups' timeline
|
||||||
|
def timeline
|
||||||
|
Answer.where('user_id in (?)', members.pluck(:user_id)).order(:created_at).reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,10 +3,19 @@ class Notification < ApplicationRecord
|
||||||
belongs_to :target, polymorphic: true
|
belongs_to :target, polymorphic: true
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_for, :for
|
||||||
|
define_cursor_paginator :cursored_for_type, :for_type
|
||||||
|
|
||||||
def for(recipient, options={})
|
def for(recipient, options={})
|
||||||
self.where(options.merge!(recipient: recipient)).order(:created_at).reverse_order
|
self.where(options.merge!(recipient: recipient)).order(:created_at).reverse_order
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def for_type(recipient, type, options={})
|
||||||
|
self.where(options.merge!(recipient: recipient)).where('LOWER(target_type) = ?', type).order(:created_at).reverse_order
|
||||||
|
end
|
||||||
|
|
||||||
def notify(recipient, target)
|
def notify(recipient, target)
|
||||||
return nil unless target.respond_to? :notification_type
|
return nil unless target.respond_to? :notification_type
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
class Question < ApplicationRecord
|
class Question < ApplicationRecord
|
||||||
|
include Question::AnswerMethods
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_many :answers, dependent: :destroy
|
has_many :answers, dependent: :destroy
|
||||||
has_many :inboxes, dependent: :destroy
|
has_many :inboxes, dependent: :destroy
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Question::AnswerMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_answers, :ordered_answers
|
||||||
|
|
||||||
|
def ordered_answers
|
||||||
|
answers
|
||||||
|
.order(:created_at)
|
||||||
|
.reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,4 +1,10 @@
|
||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
|
include User::AnswerMethods
|
||||||
|
include User::InboxMethods
|
||||||
|
include User::QuestionMethods
|
||||||
|
include User::RelationshipMethods
|
||||||
|
include User::TimelineMethods
|
||||||
|
|
||||||
# Include default devise modules. Others available are:
|
# Include default devise modules. Others available are:
|
||||||
# :confirmable, :lockable, :timeoutable and :omniauthable
|
# :confirmable, :lockable, :timeoutable and :omniauthable
|
||||||
devise :database_authenticatable, :async, :registerable,
|
devise :database_authenticatable, :async, :registerable,
|
||||||
|
@ -100,11 +106,6 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# @return [Array] the users' timeline
|
|
||||||
def timeline
|
|
||||||
Answer.where("user_id in (?) OR user_id = ?", friend_ids, id).order(:created_at).reverse_order
|
|
||||||
end
|
|
||||||
|
|
||||||
# follows an user.
|
# follows an user.
|
||||||
def follow(target_user)
|
def follow(target_user)
|
||||||
active_relationships.create(target: target_user)
|
active_relationships.create(target: target_user)
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module User::AnswerMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_answers, :ordered_answers
|
||||||
|
|
||||||
|
def ordered_answers
|
||||||
|
answers
|
||||||
|
.order(:created_at)
|
||||||
|
.reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module User::InboxMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_inbox, :ordered_inbox
|
||||||
|
|
||||||
|
def ordered_inbox
|
||||||
|
inboxes
|
||||||
|
.includes(:question, :user)
|
||||||
|
.order(:created_at)
|
||||||
|
.reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module User::QuestionMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_questions, :ordered_questions
|
||||||
|
|
||||||
|
def ordered_questions
|
||||||
|
questions
|
||||||
|
.order(:created_at)
|
||||||
|
.reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module User::RelationshipMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_friends, :ordered_friends
|
||||||
|
define_cursor_paginator :cursored_followers, :ordered_followers
|
||||||
|
|
||||||
|
def ordered_friends
|
||||||
|
friends.reverse_order
|
||||||
|
end
|
||||||
|
|
||||||
|
def ordered_followers
|
||||||
|
followers.reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module User::TimelineMethods
|
||||||
|
include CursorPaginatable
|
||||||
|
|
||||||
|
define_cursor_paginator :cursored_timeline, :timeline
|
||||||
|
|
||||||
|
# @return [Array] the users' timeline
|
||||||
|
def timeline
|
||||||
|
Answer.where('user_id in (?) OR user_id = ?', friend_ids, id).order(:created_at).reverse_order
|
||||||
|
end
|
||||||
|
end
|
|
@ -10,9 +10,9 @@
|
||||||
- @timeline.each do |answer|
|
- @timeline.each do |answer|
|
||||||
= render 'shared/answerbox', a: answer
|
= render 'shared/answerbox', a: answer
|
||||||
|
|
||||||
#pagination= will_paginate @timeline, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @timeline_last_id
|
||||||
|
|
||||||
- if @timeline.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @timeline.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @timeline_last_id }}
|
||||||
= t 'views.actions.load'
|
= t 'views.actions.load'
|
||||||
.visible-xs= render 'shared/links'
|
.visible-xs= render 'shared/links'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#timeline').append('<% @timeline.each do |answer|
|
$('#timeline').append('<% @timeline.each do |answer|
|
||||||
%><%= j render 'shared/answerbox', a: answer
|
%><%= j render 'shared/answerbox', a: answer
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @timeline.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @timeline, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @timeline_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
- if @inbox.empty?
|
- if @inbox.empty?
|
||||||
= t 'views.inbox.empty'
|
= t 'views.inbox.empty'
|
||||||
|
|
||||||
#pagination= will_paginate @inbox, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @inbox_last_id
|
||||||
|
|
||||||
- if @inbox.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @inbox.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @inbox_last_id }}
|
||||||
= t 'views.actions.load'
|
= t 'views.actions.load'
|
||||||
|
|
||||||
.col-md-9.col-xs-12.col-sm-8.visible-xs
|
.col-md-9.col-xs-12.col-sm-8.visible-xs
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
$('#entries').append('<% @inbox.each do |i|
|
$('#entries').append('<% @inbox.each do |i|
|
||||||
%><%= j render 'inbox/entry', i: i
|
%><%= j render 'inbox/entry', i: i
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @inbox.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @inbox, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @inbox_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
<% Inbox.where(id: @inbox.pluck(:id)).update_all(new: false) %>
|
<% Inbox.where(id: @inbox.pluck(:id)).update_all(new: false) %>
|
||||||
|
|
|
@ -18,9 +18,9 @@
|
||||||
- @notifications.each do |notification|
|
- @notifications.each do |notification|
|
||||||
= render 'notifications/notification', notification: notification
|
= render 'notifications/notification', notification: notification
|
||||||
|
|
||||||
#pagination= will_paginate @notifications, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @notifications_last_id, permitted_params: %i[type]
|
||||||
|
|
||||||
- if @notifications.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @notifications.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @notifications_last_id }}
|
||||||
Load more
|
Load more
|
||||||
- Notification.for(current_user).update_all(new: false)
|
- Notification.for(current_user).update_all(new: false)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#notifications').append('<% @notifications.each do |notification|
|
$('#notifications').append('<% @notifications.each do |notification|
|
||||||
%><%= j render 'notifications/notification', notification: notification
|
%><%= j render 'notifications/notification', notification: notification
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @notifications.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @notifications, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @notifications_last_id, permitted_params: %i[type] %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
- @timeline.each do |answer|
|
- @timeline.each do |answer|
|
||||||
= render 'shared/answerbox', a: answer
|
= render 'shared/answerbox', a: answer
|
||||||
|
|
||||||
#pagination= will_paginate @timeline, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @timeline_last_id
|
||||||
|
|
||||||
- if @timeline.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @timeline.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @timeline_last_id }}
|
||||||
Load more
|
Load more
|
||||||
.visible-xs= render 'shared/links'
|
.visible-xs= render 'shared/links'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#timeline').append('<% @timeline.each do |answer|
|
$('#timeline').append('<% @timeline.each do |answer|
|
||||||
%><%= j render 'shared/answerbox', a: answer
|
%><%= j render 'shared/answerbox', a: answer
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @timeline.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @timeline, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @timeline_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
- @answers.each do |a|
|
- @answers.each do |a|
|
||||||
= render 'shared/answerbox', a: a, show_question: false
|
= render 'shared/answerbox', a: a, show_question: false
|
||||||
|
|
||||||
#pagination= will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @answers_last_id
|
||||||
|
|
||||||
- if @answers.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @answers.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @answers_last_id }}
|
||||||
Load more
|
Load more
|
||||||
|
|
||||||
- if user_signed_in? and !current_user.answered? @question and current_user != @question.user and @question.user.privacy_allow_stranger_answers
|
- if user_signed_in? and !current_user.answered? @question and current_user != @question.user and @question.user.privacy_allow_stranger_answers
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#answers').append('<% @answers.each do |answer|
|
$('#answers').append('<% @answers.each do |answer|
|
||||||
%><%= j render 'shared/answerbox', a: answer, show_question: false
|
%><%= j render 'shared/answerbox', a: answer, show_question: false
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @answers.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @answers_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
-# this renders a pagination html to keep compatibility with the current pagination js
|
||||||
|
-# it _should_ be replaced with something else entirely later on.
|
||||||
|
- permitted_params ||= []
|
||||||
|
#pagination
|
||||||
|
%ul.pagination
|
||||||
|
%li.next{class: more_data_available ? nil : "disabled"}
|
||||||
|
- if more_data_available
|
||||||
|
%a{rel: :next, href: url_for(params.permit(*permitted_params).merge(last_id: last_id))}
|
||||||
|
Next page
|
||||||
|
- else
|
||||||
|
Next page
|
|
@ -9,9 +9,9 @@
|
||||||
- @timeline.each do |answer|
|
- @timeline.each do |answer|
|
||||||
= render 'shared/answerbox', a: answer
|
= render 'shared/answerbox', a: answer
|
||||||
|
|
||||||
#pagination= will_paginate @timeline, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @timeline_last_id
|
||||||
|
|
||||||
- if @timeline.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @timeline.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @timeline_last_id }}
|
||||||
Load more
|
Load more
|
||||||
.visible-xs= render 'shared/links'
|
.visible-xs= render 'shared/links'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#timeline').append('<% @timeline.each do |answer|
|
$('#timeline').append('<% @timeline.each do |answer|
|
||||||
%><%= j render 'shared/answerbox', a: answer
|
%><%= j render 'shared/answerbox', a: answer
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @timeline.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @timeline, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @timeline_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
- @questions.each do |q|
|
- @questions.each do |q|
|
||||||
= render 'shared/question', q: q, type: nil
|
= render 'shared/question', q: q, type: nil
|
||||||
|
|
||||||
#pagination= will_paginate @questions, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @questions_last_id
|
||||||
|
|
||||||
- if @questions.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @questions.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @questions_last_id }}
|
||||||
= t 'views.actions.load'
|
= t 'views.actions.load'
|
||||||
.visible-xs= render 'shared/links'
|
.visible-xs= render 'shared/links'
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#questions').append('<% @questions.each do |q|
|
$('#questions').append('<% @questions.each do |q|
|
||||||
%><%= j render 'shared/question', q: q, type: nil
|
%><%= j render 'shared/question', q: q, type: nil
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @questions.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @questions, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @questions_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
- @answers.each do |a|
|
- @answers.each do |a|
|
||||||
= render 'shared/answerbox', a: a
|
= render 'shared/answerbox', a: a
|
||||||
|
|
||||||
#pagination= will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @answers_last_id
|
||||||
|
|
||||||
- if @answers.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @answers.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @answers_last_id }}
|
||||||
= t 'views.actions.load'
|
= t 'views.actions.load'
|
||||||
.visible-xs= render 'shared/links'
|
.visible-xs= render 'shared/links'
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#answers').append('<% @answers.each do |a|
|
$('#answers').append('<% @answers.each do |a|
|
||||||
%><%= j render 'shared/answerbox', a: a
|
%><%= j render 'shared/answerbox', a: a
|
||||||
%><% end %>');
|
%><% end %>');
|
||||||
<% if @answers.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @answers, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @answers_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
.col-md-4.col-sm-6.col-xs-12
|
.col-md-4.col-sm-6.col-xs-12
|
||||||
= render 'shared/userbox', user: user
|
= render 'shared/userbox', user: user
|
||||||
|
|
||||||
#pagination= will_paginate @users, renderer: BootstrapPagination::Rails, page_links: false
|
= render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @users_last_id
|
||||||
|
|
||||||
- if @users.next_page
|
- if @more_data_available
|
||||||
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @users.current_page }}
|
%button#load-more-btn.btn.btn-default{type: :button, data: { last_id: @users_last_id }}
|
||||||
= t 'views.actions.load'
|
= t 'views.actions.load'
|
||||||
.visible-xs= render 'shared/links'
|
.visible-xs= render 'shared/links'
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
$('#users').append('<% @users.each do |user|
|
$('#users').append('<% @users.each do |user|
|
||||||
%><div class="col-md-4 col-sm-6 col-xs-12"><%= j render 'shared/userbox', user: user
|
%><div class="col-md-4 col-sm-6 col-xs-12"><%= j render 'shared/userbox', user: user
|
||||||
%></div><% end %>');
|
%></div><% end %>');
|
||||||
<% if @users.next_page %>
|
<% if @more_data_available %>
|
||||||
$('#pagination').html('<%= j will_paginate @users, renderer: BootstrapPagination::Rails, page_links: false %>');
|
$('#pagination').html('<%= j render 'shared/cursored_pagination_dummy', more_data_available: @more_data_available, last_id: @users_last_id %>');
|
||||||
<% else %>
|
<% else %>
|
||||||
$('#pagination, #load-more-btn').remove();
|
$('#pagination, #load-more-btn').remove();
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
WillPaginate.per_page = APP_CONFIG['items_per_page']
|
|
|
@ -1,12 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
# workaround to get pagination right
|
# workaround to get pagination right
|
||||||
if defined? WillPaginate
|
|
||||||
Kaminari.configure do |config|
|
|
||||||
config.page_method_name = :per_page_kaminari
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
RailsAdmin.config do |config|
|
RailsAdmin.config do |config|
|
||||||
config.main_app_name = ['justask', 'Kontrollzentrum']
|
config.main_app_name = ['justask', 'Kontrollzentrum']
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :answer do
|
||||||
|
transient do
|
||||||
|
question_content { Faker::Lorem.sentence }
|
||||||
|
end
|
||||||
|
|
||||||
|
content { Faker::Lorem.sentence }
|
||||||
|
question { FactoryBot.build(:question, content: question_content) }
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,9 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
FactoryBot.define do
|
||||||
|
factory :question do
|
||||||
|
user { nil }
|
||||||
|
content { Faker::Lorem.sentence }
|
||||||
|
author_is_anonymous { true }
|
||||||
|
end
|
||||||
|
end
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
FactoryBot.define do
|
FactoryBot.define do
|
||||||
factory :user do
|
factory :user do
|
||||||
sequence(:screen_name) { |i| "#{Faker::Internet.username(specifier: 0..12, separators: %w(_))}#{i}" }
|
sequence(:screen_name) { |i| "#{Faker::Internet.username(specifier: 0..12, separators: %w[_])}#{i}" }
|
||||||
sequence(:email) { |i| "#{i}#{Faker::Internet.email}" }
|
sequence(:email) { |i| "#{i}#{Faker::Internet.email}" }
|
||||||
password { "P4s5w0rD" }
|
password { 'P4s5w0rD' }
|
||||||
confirmed_at { Time.now.utc }
|
confirmed_at { Time.now.utc }
|
||||||
display_name { Faker::Name.name }
|
display_name { Faker::Name.name }
|
||||||
|
|
|
@ -1,28 +1,158 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
RSpec.describe User, :type => :model do
|
RSpec.describe User, type: :model do
|
||||||
before :each do
|
let!(:me) { FactoryBot.create :user }
|
||||||
@user = User.new(
|
|
||||||
|
describe 'basic assigns' do
|
||||||
|
before :each do
|
||||||
|
@user = User.new(
|
||||||
screen_name: 'FunnyMeme2004',
|
screen_name: 'FunnyMeme2004',
|
||||||
password: 'y_u_no_secure_password?',
|
password: 'y_u_no_secure_password?',
|
||||||
email: 'nice.meme@nsa.gov'
|
email: 'nice.meme@nsa.gov'
|
||||||
)
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { @user }
|
||||||
|
|
||||||
|
it { should respond_to(:email) }
|
||||||
|
|
||||||
|
it '#email returns a string' do
|
||||||
|
expect(@user.email).to match 'nice.meme@nsa.gov'
|
||||||
|
end
|
||||||
|
|
||||||
|
it '#motivation_header has a default value' do
|
||||||
|
expect(@user.motivation_header).to match ''
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'does not save an invalid screen name' do
|
||||||
|
@user.screen_name = '$Funny-Meme-%&2004'
|
||||||
|
expect { @user.save! }.to raise_error(ActiveRecord::RecordInvalid)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
subject { @user }
|
# -- User::TimelineMethods --
|
||||||
|
|
||||||
it { should respond_to(:email) }
|
shared_examples_for 'result is blank' do
|
||||||
|
it 'result is blank' do
|
||||||
it '#email returns a string' do
|
expect(subject).to be_blank
|
||||||
expect(@user.email).to match 'nice.meme@nsa.gov'
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it '#motivation_header has a default value' do
|
describe '#timeline' do
|
||||||
expect(@user.motivation_header).to match ''
|
subject { me.timeline }
|
||||||
|
|
||||||
|
context 'user answered nothing and is not following anyone' do
|
||||||
|
include_examples 'result is blank'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'user answered something and is not following anyone' do
|
||||||
|
let(:answer) { FactoryBot.create(:answer, user: me) }
|
||||||
|
|
||||||
|
let(:expected) { [answer] }
|
||||||
|
|
||||||
|
it 'includes the answer' do
|
||||||
|
expect(subject).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'user answered something and follows users with answers' do
|
||||||
|
let(:user1) { FactoryBot.create(:user) }
|
||||||
|
let(:user2) { FactoryBot.create(:user) }
|
||||||
|
let(:answer1) { FactoryBot.create(:answer, user: user1, created_at: 12.hours.ago) }
|
||||||
|
let(:answer2) { FactoryBot.create(:answer, user: me, created_at: 1.day.ago) }
|
||||||
|
let(:answer3) { FactoryBot.create(:answer, user: user2, created_at: 10.minutes.ago) }
|
||||||
|
let(:answer4) { FactoryBot.create(:answer, user: user1, created_at: Time.now.utc) }
|
||||||
|
|
||||||
|
let!(:expected) do
|
||||||
|
[answer4, answer3, answer1, answer2]
|
||||||
|
end
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
me.follow(user1)
|
||||||
|
me.follow(user2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes all answers' do
|
||||||
|
expect(subject).to include(answer1)
|
||||||
|
expect(subject).to include(answer2)
|
||||||
|
expect(subject).to include(answer3)
|
||||||
|
expect(subject).to include(answer4)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'result is ordered by created_at in reverse order' do
|
||||||
|
expect(subject).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not save an invalid screen name' do
|
describe '#cursored_timeline' do
|
||||||
@user.screen_name = '$Funny-Meme-%&2004'
|
let(:last_id) { nil }
|
||||||
expect{@user.save!}.to raise_error(ActiveRecord::RecordInvalid)
|
|
||||||
|
subject { me.cursored_timeline(last_id: last_id, size: 3) }
|
||||||
|
|
||||||
|
context 'user answered nothing and is not following anyone' do
|
||||||
|
include_examples 'result is blank'
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'user answered something and is not following anyone' do
|
||||||
|
let(:answer) { FactoryBot.create(:answer, user: me) }
|
||||||
|
|
||||||
|
let(:expected) { [answer] }
|
||||||
|
|
||||||
|
it 'includes the answer' do
|
||||||
|
expect(subject).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'user answered something and follows users with answers' do
|
||||||
|
let(:user1) { FactoryBot.create(:user) }
|
||||||
|
let(:user2) { FactoryBot.create(:user) }
|
||||||
|
let!(:answer1) { FactoryBot.create(:answer, user: me, created_at: 1.day.ago) }
|
||||||
|
let!(:answer2) { FactoryBot.create(:answer, user: user1, created_at: 12.hours.ago) }
|
||||||
|
let!(:answer3) { FactoryBot.create(:answer, user: user2, created_at: 10.minutes.ago) }
|
||||||
|
let!(:answer4) { FactoryBot.create(:answer, user: user1, created_at: Time.now.utc) }
|
||||||
|
|
||||||
|
before(:each) do
|
||||||
|
me.follow(user1)
|
||||||
|
me.follow(user2)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'last_id is nil' do
|
||||||
|
let(:last_id) { nil }
|
||||||
|
let(:expected) do
|
||||||
|
[answer4, answer3, answer2]
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes three answers' do
|
||||||
|
expect(subject).not_to include(answer1)
|
||||||
|
expect(subject).to include(answer2)
|
||||||
|
expect(subject).to include(answer3)
|
||||||
|
expect(subject).to include(answer4)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'result is ordered by created_at in reverse order' do
|
||||||
|
expect(subject).to eq(expected)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'last_id is answer2.id' do
|
||||||
|
let(:last_id) { answer2.id }
|
||||||
|
|
||||||
|
it 'includes answer1' do
|
||||||
|
expect(subject).to include(answer1)
|
||||||
|
expect(subject).not_to include(answer2)
|
||||||
|
expect(subject).not_to include(answer3)
|
||||||
|
expect(subject).not_to include(answer4)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'last_id is answer1.id' do
|
||||||
|
let(:last_id) { answer1.id }
|
||||||
|
|
||||||
|
include_examples 'result is blank'
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue