##// END OF EJS Templates
Restores object count and adds offset/limit attributes to API responses for paginated collections (#6140)....
Jean-Philippe Lang -
r4375:00d50157d3d6
parent child
Show More
@@ -349,6 +349,23 class ApplicationController < ActionController::Base
349 per_page
349 per_page
350 end
350 end
351
351
352 def api_offset_and_limit
353 offset = nil
354 if params[:offset].present?
355 offset = params[:offset].to_i
356 if offset < 0
357 offset = 0
358 end
359 end
360 limit = params[:limit].to_i
361 if limit < 1
362 limit = 25
363 elsif limit > 100
364 limit = 100
365 end
366 [offset, limit]
367 end
368
352 # qvalues http header parser
369 # qvalues http header parser
353 # code taken from webrick
370 # code taken from webrick
354 def parse_qvalues(value)
371 def parse_qvalues(value)
@@ -65,21 +65,24 class IssuesController < ApplicationController
65 sort_update(@query.sortable_columns)
65 sort_update(@query.sortable_columns)
66
66
67 if @query.valid?
67 if @query.valid?
68 limit = case params[:format]
68 case params[:format]
69 when 'csv', 'pdf'
69 when 'csv', 'pdf'
70 Setting.issues_export_limit.to_i
70 @limit = Setting.issues_export_limit.to_i
71 when 'atom'
71 when 'atom'
72 Setting.feeds_limit.to_i
72 @limit = Setting.feeds_limit.to_i
73 when 'xml', 'json'
74 @offset, @limit = api_offset_and_limit
73 else
75 else
74 per_page_option
76 @limit = per_page_option
75 end
77 end
76
78
77 @issue_count = @query.issue_count
79 @issue_count = @query.issue_count
78 @issue_pages = Paginator.new self, @issue_count, limit, params['page']
80 @issue_pages = Paginator.new self, @issue_count, @limit, params['page']
81 @offset ||= @issue_pages.current.offset
79 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
82 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
80 :order => sort_clause,
83 :order => sort_clause,
81 :offset => @issue_pages.current.offset,
84 :offset => @offset,
82 :limit => limit)
85 :limit => @limit)
83 @issue_count_by_group = @query.issue_count_by_group
86 @issue_count_by_group = @query.issue_count_by_group
84
87
85 respond_to do |format|
88 respond_to do |format|
@@ -30,6 +30,13 class UsersController < ApplicationController
30 sort_init 'login', 'asc'
30 sort_init 'login', 'asc'
31 sort_update %w(login firstname lastname mail admin created_on last_login_on)
31 sort_update %w(login firstname lastname mail admin created_on last_login_on)
32
32
33 case params[:format]
34 when 'xml', 'json'
35 @offset, @limit = api_offset_and_limit
36 else
37 @limit = per_page_option
38 end
39
33 @status = params[:status] ? params[:status].to_i : 1
40 @status = params[:status] ? params[:status].to_i : 1
34 c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
41 c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
35
42
@@ -39,13 +46,13 class UsersController < ApplicationController
39 end
46 end
40
47
41 @user_count = User.count(:conditions => c.conditions)
48 @user_count = User.count(:conditions => c.conditions)
42 @user_pages = Paginator.new self, @user_count,
49 @user_pages = Paginator.new self, @user_count, @limit, params['page']
43 per_page_option,
50 @offset ||= @user_pages.current.offset
44 params['page']
51 @users = User.find :all,
45 @users = User.find :all,:order => sort_clause,
52 :order => sort_clause,
46 :conditions => c.conditions,
53 :conditions => c.conditions,
47 :limit => @user_pages.items_per_page,
54 :limit => @limit,
48 :offset => @user_pages.current.offset
55 :offset => @offset
49
56
50 respond_to do |format|
57 respond_to do |format|
51 format.html { render :layout => !request.xhr? }
58 format.html { render :layout => !request.xhr? }
@@ -877,6 +877,18 module ApplicationHelper
877 @included_in_api_response.include?(arg.to_s)
877 @included_in_api_response.include?(arg.to_s)
878 end
878 end
879
879
880 # Returns options or nil if nometa param or X-Redmine-Nometa header
881 # was set in the request
882 def api_meta(options)
883 if params[:nometa].present? || request.headers['X-Redmine-Nometa']
884 # compatibility mode for activeresource clients that raise
885 # an error when unserializing an array with attributes
886 nil
887 else
888 options
889 end
890 end
891
880 private
892 private
881
893
882 def wiki_helper
894 def wiki_helper
@@ -1,4 +1,4
1 api.array :issues do
1 api.array :issues, api_meta(:total_count => @issue_count, :offset => @offset, :limit => @limit) do
2 @issues.each do |issue|
2 @issues.each do |issue|
3 api.issue do
3 api.issue do
4 api.id issue.id
4 api.id issue.id
@@ -1,4 +1,4
1 api.array :users do
1 api.array :users, api_meta(:total_count => @user_count, :offset => @offset, :limit => @limit) do
2 @users.each do |user|
2 @users.each do |user|
3 api.user do
3 api.user do
4 api.id user.id
4 api.id user.id
@@ -25,11 +25,12 module Redmine
25 @struct = [{}]
25 @struct = [{}]
26 end
26 end
27
27
28 def array(tag, &block)
28 def array(tag, options={}, &block)
29 @struct << []
29 @struct << []
30 block.call(self)
30 block.call(self)
31 ret = @struct.pop
31 ret = @struct.pop
32 @struct.last[tag] = ret
32 @struct.last[tag] = ret
33 @struct.last.merge!(options) if options
33 end
34 end
34
35
35 def method_missing(sym, *args, &block)
36 def method_missing(sym, *args, &block)
@@ -37,7 +37,7 module Redmine
37 end
37 end
38
38
39 def array(name, options={}, &block)
39 def array(name, options={}, &block)
40 __send__ name, options.merge(:type => 'array'), &block
40 __send__ name, (options || {}).merge(:type => 'array'), &block
41 end
41 end
42 end
42 end
43 end
43 end
@@ -46,10 +46,60 class ApiTest::IssuesTest < ActionController::IntegrationTest
46 Setting.rest_api_enabled = '1'
46 Setting.rest_api_enabled = '1'
47 end
47 end
48
48
49 context "/index.xml" do
49 # Use a private project to make sure auth is really working and not just
50 # Use a private project to make sure auth is really working and not just
50 # only showing public issues.
51 # only showing public issues.
51 context "/index.xml" do
52 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
52 should_allow_api_authentication(:get, "/projects/private-child/issues.xml")
53
54 should "contain metadata" do
55 get '/issues.xml'
56
57 assert_tag :tag => 'issues',
58 :attributes => {
59 :type => 'array',
60 :total_count => assigns(:issue_count),
61 :limit => 25,
62 :offset => 0
63 }
64 end
65
66 context "with offset and limit" do
67 should "use the params" do
68 get '/issues.xml?offset=2&limit=3'
69
70 assert_equal 3, assigns(:limit)
71 assert_equal 2, assigns(:offset)
72 assert_tag :tag => 'issues', :children => {:count => 3, :only => {:tag => 'issue'}}
73 end
74 end
75
76 context "with nometa param" do
77 should "not contain metadata" do
78 get '/issues.xml?nometa=1'
79
80 assert_tag :tag => 'issues',
81 :attributes => {
82 :type => 'array',
83 :total_count => nil,
84 :limit => nil,
85 :offset => nil
86 }
87 end
88 end
89
90 context "with nometa header" do
91 should "not contain metadata" do
92 get '/issues.xml', {}, {'X-Redmine-Nometa' => '1'}
93
94 assert_tag :tag => 'issues',
95 :attributes => {
96 :type => 'array',
97 :total_count => nil,
98 :limit => nil,
99 :offset => nil
100 }
101 end
102 end
53 end
103 end
54
104
55 context "/index.json" do
105 context "/index.json" do
General Comments 0
You need to be logged in to leave comments. Login now