* Make Array-creation behavior of Paginable more predictable
Paginable.paginate_by_id usually returns ActiveRecord::Relation, but it
returns an Array if min_id option is present. The behavior caused problems
fixed with the following commits:
-
552e886b648faa2a2229d86c7fd9abc8bb5ff99c
-
b63ede5005d33b52266650ec716d345f166e2df0
-
64ef37b89de806f49cc59e011aa0ee2039c82c46
To prevent from recurring similar problems, this commit introduces two
changes:
- The scope now always returns an Array whether min_id option is present
or not.
- The scope is renamed to to_a_paginated_by_id to clarify it returns an
Array.
* Transform Paginable.to_a_paginated_by_id from a scope to a class method
https://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-scope
> The method is intended to return an ActiveRecord::Relation object, which
> is composable with other scopes.
Paginable.to_a_paginated_by_id returns an Array and is not appropriate
as a scope.
private
def set_accounts
- @accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite]).paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+ @accounts = filtered_accounts.order(id: :desc).includes(user: [:invite_request, :invite]).to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def set_account
private
def set_reports
- @reports = filtered_reports.order(id: :desc).with_accounts.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+ @reports = filtered_reports.order(id: :desc).with_accounts.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def set_report
end
def results
- @_results ||= account_bookmarks.eager_load(:status).paginate_by_id(
+ @_results ||= account_bookmarks.eager_load(:status).to_a_paginated_by_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)
def paginated_conversations
AccountConversation.where(account: current_account)
- .paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+ .to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def insert_pagination_headers
end
def set_encrypted_messages
- @encrypted_messages = @current_device.encrypted_messages.paginate_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
+ @encrypted_messages = @current_device.encrypted_messages.to_a_paginated_by_id(limit_param(LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def insert_pagination_headers
end
def results
- @_results ||= account_favourites.eager_load(:status).paginate_by_id(
+ @_results ||= account_favourites.eager_load(:status).to_a_paginated_by_id(
limit_param(DEFAULT_STATUSES_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)
private
def set_statuses
- @statuses = current_account.scheduled_statuses.paginate_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
+ @statuses = current_account.scheduled_statuses.to_a_paginated_by_id(limit_param(DEFAULT_STATUSES_LIMIT), params_slice(:max_id, :since_id, :min_id))
end
def set_status
end
def cache_collection_paginated_by_id(raw, klass, limit, options)
- cache_collection raw.cache_ids.paginate_by_id(limit, options), klass
+ cache_collection raw.cache_ids.to_a_paginated_by_id(limit, options), klass
end
end
end
class << self
- def paginate_by_id(limit, options = {})
+ def to_a_paginated_by_id(limit, options = {})
if options[:min_id]
paginate_by_min_id(limit, options[:min_id]).reverse
else
- paginate_by_max_id(limit, options[:max_id], options[:since_id])
+ paginate_by_max_id(limit, options[:max_id], options[:since_id]).to_a
end
end
query
}
- scope :paginate_by_id, ->(limit, options = {}) {
+ def self.to_a_paginated_by_id(limit, options = {})
if options[:min_id].present?
paginate_by_min_id(limit, options[:min_id]).reverse
else
- paginate_by_max_id(limit, options[:max_id], options[:since_id])
+ paginate_by_max_id(limit, options[:max_id], options[:since_id]).to_a
end
- }
+ end
end
end