Restores object count and adds offset/limit attributes to API responses for paginated collections (#6140).
git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@4489 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
67f1131a20
commit
00d50157d3
|
@ -349,6 +349,23 @@ class ApplicationController < ActionController::Base
|
||||||
per_page
|
per_page
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def api_offset_and_limit
|
||||||
|
offset = nil
|
||||||
|
if params[:offset].present?
|
||||||
|
offset = params[:offset].to_i
|
||||||
|
if offset < 0
|
||||||
|
offset = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
limit = params[:limit].to_i
|
||||||
|
if limit < 1
|
||||||
|
limit = 25
|
||||||
|
elsif limit > 100
|
||||||
|
limit = 100
|
||||||
|
end
|
||||||
|
[offset, limit]
|
||||||
|
end
|
||||||
|
|
||||||
# qvalues http header parser
|
# qvalues http header parser
|
||||||
# code taken from webrick
|
# code taken from webrick
|
||||||
def parse_qvalues(value)
|
def parse_qvalues(value)
|
||||||
|
|
|
@ -65,21 +65,24 @@ class IssuesController < ApplicationController
|
||||||
sort_update(@query.sortable_columns)
|
sort_update(@query.sortable_columns)
|
||||||
|
|
||||||
if @query.valid?
|
if @query.valid?
|
||||||
limit = case params[:format]
|
case params[:format]
|
||||||
when 'csv', 'pdf'
|
when 'csv', 'pdf'
|
||||||
Setting.issues_export_limit.to_i
|
@limit = Setting.issues_export_limit.to_i
|
||||||
when 'atom'
|
when 'atom'
|
||||||
Setting.feeds_limit.to_i
|
@limit = Setting.feeds_limit.to_i
|
||||||
|
when 'xml', 'json'
|
||||||
|
@offset, @limit = api_offset_and_limit
|
||||||
else
|
else
|
||||||
per_page_option
|
@limit = per_page_option
|
||||||
end
|
end
|
||||||
|
|
||||||
@issue_count = @query.issue_count
|
@issue_count = @query.issue_count
|
||||||
@issue_pages = Paginator.new self, @issue_count, limit, params['page']
|
@issue_pages = Paginator.new self, @issue_count, @limit, params['page']
|
||||||
|
@offset ||= @issue_pages.current.offset
|
||||||
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
|
@issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
|
||||||
:order => sort_clause,
|
:order => sort_clause,
|
||||||
:offset => @issue_pages.current.offset,
|
:offset => @offset,
|
||||||
:limit => limit)
|
:limit => @limit)
|
||||||
@issue_count_by_group = @query.issue_count_by_group
|
@issue_count_by_group = @query.issue_count_by_group
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
|
|
|
@ -30,6 +30,13 @@ class UsersController < ApplicationController
|
||||||
sort_init 'login', 'asc'
|
sort_init 'login', 'asc'
|
||||||
sort_update %w(login firstname lastname mail admin created_on last_login_on)
|
sort_update %w(login firstname lastname mail admin created_on last_login_on)
|
||||||
|
|
||||||
|
case params[:format]
|
||||||
|
when 'xml', 'json'
|
||||||
|
@offset, @limit = api_offset_and_limit
|
||||||
|
else
|
||||||
|
@limit = per_page_option
|
||||||
|
end
|
||||||
|
|
||||||
@status = params[:status] ? params[:status].to_i : 1
|
@status = params[:status] ? params[:status].to_i : 1
|
||||||
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
|
c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
|
||||||
|
|
||||||
|
@ -39,13 +46,13 @@ class UsersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
@user_count = User.count(:conditions => c.conditions)
|
@user_count = User.count(:conditions => c.conditions)
|
||||||
@user_pages = Paginator.new self, @user_count,
|
@user_pages = Paginator.new self, @user_count, @limit, params['page']
|
||||||
per_page_option,
|
@offset ||= @user_pages.current.offset
|
||||||
params['page']
|
@users = User.find :all,
|
||||||
@users = User.find :all,:order => sort_clause,
|
:order => sort_clause,
|
||||||
:conditions => c.conditions,
|
:conditions => c.conditions,
|
||||||
:limit => @user_pages.items_per_page,
|
:limit => @limit,
|
||||||
:offset => @user_pages.current.offset
|
:offset => @offset
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { render :layout => !request.xhr? }
|
format.html { render :layout => !request.xhr? }
|
||||||
|
|
|
@ -877,6 +877,18 @@ module ApplicationHelper
|
||||||
@included_in_api_response.include?(arg.to_s)
|
@included_in_api_response.include?(arg.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns options or nil if nometa param or X-Redmine-Nometa header
|
||||||
|
# was set in the request
|
||||||
|
def api_meta(options)
|
||||||
|
if params[:nometa].present? || request.headers['X-Redmine-Nometa']
|
||||||
|
# compatibility mode for activeresource clients that raise
|
||||||
|
# an error when unserializing an array with attributes
|
||||||
|
nil
|
||||||
|
else
|
||||||
|
options
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def wiki_helper
|
def wiki_helper
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
api.array :issues do
|
api.array :issues, api_meta(:total_count => @issue_count, :offset => @offset, :limit => @limit) do
|
||||||
@issues.each do |issue|
|
@issues.each do |issue|
|
||||||
api.issue do
|
api.issue do
|
||||||
api.id issue.id
|
api.id issue.id
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
api.array :users do
|
api.array :users, api_meta(:total_count => @user_count, :offset => @offset, :limit => @limit) do
|
||||||
@users.each do |user|
|
@users.each do |user|
|
||||||
api.user do
|
api.user do
|
||||||
api.id user.id
|
api.id user.id
|
||||||
|
|
|
@ -25,11 +25,12 @@ module Redmine
|
||||||
@struct = [{}]
|
@struct = [{}]
|
||||||
end
|
end
|
||||||
|
|
||||||
def array(tag, &block)
|
def array(tag, options={}, &block)
|
||||||
@struct << []
|
@struct << []
|
||||||
block.call(self)
|
block.call(self)
|
||||||
ret = @struct.pop
|
ret = @struct.pop
|
||||||
@struct.last[tag] = ret
|
@struct.last[tag] = ret
|
||||||
|
@struct.last.merge!(options) if options
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_missing(sym, *args, &block)
|
def method_missing(sym, *args, &block)
|
||||||
|
|
|
@ -37,7 +37,7 @@ module Redmine
|
||||||
end
|
end
|
||||||
|
|
||||||
def array(name, options={}, &block)
|
def array(name, options={}, &block)
|
||||||
__send__ name, options.merge(:type => 'array'), &block
|
__send__ name, (options || {}).merge(:type => 'array'), &block
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -46,10 +46,60 @@ class ApiTest::IssuesTest < ActionController::IntegrationTest
|
||||||
Setting.rest_api_enabled = '1'
|
Setting.rest_api_enabled = '1'
|
||||||
end
|
end
|
||||||
|
|
||||||
# Use a private project to make sure auth is really working and not just
|
|
||||||
# only showing public issues.
|
|
||||||
context "/index.xml" do
|
context "/index.xml" do
|
||||||
|
# Use a private project to make sure auth is really working and not just
|
||||||
|
# only showing public issues.
|
||||||
should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
|
should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
|
||||||
|
|
||||||
|
should "contain metadata" do
|
||||||
|
get '/issues.xml'
|
||||||
|
|
||||||
|
assert_tag :tag => 'issues',
|
||||||
|
:attributes => {
|
||||||
|
:type => 'array',
|
||||||
|
:total_count => assigns(:issue_count),
|
||||||
|
:limit => 25,
|
||||||
|
:offset => 0
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with offset and limit" do
|
||||||
|
should "use the params" do
|
||||||
|
get '/issues.xml?offset=2&limit=3'
|
||||||
|
|
||||||
|
assert_equal 3, assigns(:limit)
|
||||||
|
assert_equal 2, assigns(:offset)
|
||||||
|
assert_tag :tag => 'issues', :children => {:count => 3, :only => {:tag => 'issue'}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with nometa param" do
|
||||||
|
should "not contain metadata" do
|
||||||
|
get '/issues.xml?nometa=1'
|
||||||
|
|
||||||
|
assert_tag :tag => 'issues',
|
||||||
|
:attributes => {
|
||||||
|
:type => 'array',
|
||||||
|
:total_count => nil,
|
||||||
|
:limit => nil,
|
||||||
|
:offset => nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context "with nometa header" do
|
||||||
|
should "not contain metadata" do
|
||||||
|
get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
|
||||||
|
|
||||||
|
assert_tag :tag => 'issues',
|
||||||
|
:attributes => {
|
||||||
|
:type => 'array',
|
||||||
|
:total_count => nil,
|
||||||
|
:limit => nil,
|
||||||
|
:offset => nil
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "/index.json" do
|
context "/index.json" do
|
||||||
|
|
Loading…
Reference in New Issue