##// 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 349 per_page
350 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 369 # qvalues http header parser
353 370 # code taken from webrick
354 371 def parse_qvalues(value)
@@ -65,21 +65,24 class IssuesController < ApplicationController
65 65 sort_update(@query.sortable_columns)
66 66
67 67 if @query.valid?
68 limit = case params[:format]
68 case params[:format]
69 69 when 'csv', 'pdf'
70 Setting.issues_export_limit.to_i
70 @limit = Setting.issues_export_limit.to_i
71 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 75 else
74 per_page_option
76 @limit = per_page_option
75 77 end
76 78
77 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 82 @issues = @query.issues(:include => [:assigned_to, :tracker, :priority, :category, :fixed_version],
80 83 :order => sort_clause,
81 :offset => @issue_pages.current.offset,
82 :limit => limit)
84 :offset => @offset,
85 :limit => @limit)
83 86 @issue_count_by_group = @query.issue_count_by_group
84 87
85 88 respond_to do |format|
@@ -30,6 +30,13 class UsersController < ApplicationController
30 30 sort_init 'login', 'asc'
31 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 40 @status = params[:status] ? params[:status].to_i : 1
34 41 c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status])
35 42
@@ -39,13 +46,13 class UsersController < ApplicationController
39 46 end
40 47
41 48 @user_count = User.count(:conditions => c.conditions)
42 @user_pages = Paginator.new self, @user_count,
43 per_page_option,
44 params['page']
45 @users = User.find :all,:order => sort_clause,
49 @user_pages = Paginator.new self, @user_count, @limit, params['page']
50 @offset ||= @user_pages.current.offset
51 @users = User.find :all,
52 :order => sort_clause,
46 53 :conditions => c.conditions,
47 :limit => @user_pages.items_per_page,
48 :offset => @user_pages.current.offset
54 :limit => @limit,
55 :offset => @offset
49 56
50 57 respond_to do |format|
51 58 format.html { render :layout => !request.xhr? }
@@ -877,6 +877,18 module ApplicationHelper
877 877 @included_in_api_response.include?(arg.to_s)
878 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 892 private
881 893
882 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 2 @issues.each do |issue|
3 3 api.issue do
4 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 2 @users.each do |user|
3 3 api.user do
4 4 api.id user.id
@@ -25,11 +25,12 module Redmine
25 25 @struct = [{}]
26 26 end
27 27
28 def array(tag, &block)
28 def array(tag, options={}, &block)
29 29 @struct << []
30 30 block.call(self)
31 31 ret = @struct.pop
32 32 @struct.last[tag] = ret
33 @struct.last.merge!(options) if options
33 34 end
34 35
35 36 def method_missing(sym, *args, &block)
@@ -37,7 +37,7 module Redmine
37 37 end
38 38
39 39 def array(name, options={}, &block)
40 __send__ name, options.merge(:type => 'array'), &block
40 __send__ name, (options || {}).merge(:type => 'array'), &block
41 41 end
42 42 end
43 43 end
@@ -46,10 +46,60 class ApiTest::IssuesTest < ActionController::IntegrationTest
46 46 Setting.rest_api_enabled = '1'
47 47 end
48 48
49 # Use a private project to make sure auth is really working and not just
50 # only showing public issues.
51 49 context "/index.xml" do
50 # Use a private project to make sure auth is really working and not just
51 # only showing public issues.
52 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 103 end
54 104
55 105 context "/index.json" do
General Comments 0
You need to be logged in to leave comments. Login now