Commit 56f3aee23b7ebc5092f0d48b8dbddffb1785bba3

Authored by Victor Costa
1 parent 92fbfd94

api: better support to choose returned fields

lib/noosfero/api/entities.rb
... ... @@ -96,14 +96,14 @@ module Noosfero
96 96 class Person < Profile
97 97 root 'people', 'person'
98 98 expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' }
99   - expose :vote_count, if: lambda { |object, options| options[:fields].present? ? options[:fields].include?('vote_count') : false}
100   - expose :comments_count, if: lambda { |object, options| options[:fields].present? ? options[:fields].include?('comments_count') : false} do |person, options|
  99 + expose :vote_count
  100 + expose :comments_count do |person, options|
101 101 person.comments.count
102 102 end
103   - expose :following_articles_count, if: lambda { |object, options| options[:fields].present? ? options[:fields].include?('following_articles_count') : false} do |person, options|
  103 + expose :following_articles_count do |person, options|
104 104 person.following_articles.count
105 105 end
106   - expose :articles_count, if: lambda { |object, options| options[:fields].present? ? options[:fields].include?('articles_count') : false} do |person, options|
  106 + expose :articles_count do |person, options|
107 107 person.articles.count
108 108 end
109 109  
... ...
lib/noosfero/api/entity.rb
... ... @@ -22,18 +22,4 @@ class Noosfero::API::Entity &lt; Grape::Entity
22 22 end
23 23 end
24 24  
25   - def self.fields_condition(fields)
26   - lambda do |object, options|
27   - return true if options[:fields].blank?
28   - fields.map { |field| options[:fields].include?(field.to_s)}.grep(true).present?
29   - end
30   - end
31   -
32   - def self.expose(*args, &block)
33   - hash = args.last.is_a?(Hash) ? args.pop : {}
34   - hash.merge!({:if => fields_condition(args)}) if hash[:if].blank?
35   - args << hash
36   - super
37   - end
38   -
39 25 end
... ...
lib/noosfero/api/helpers.rb
... ... @@ -39,6 +39,20 @@ require_relative &#39;../../find_by_contents&#39;
39 39 @environment
40 40 end
41 41  
  42 + def present_partial(model, options)
  43 + if(params[:fields].present?)
  44 + begin
  45 + fields = JSON.parse(params[:fields])
  46 + if fields.present?
  47 + options.merge!(fields.symbolize_keys.slice(:only, :except))
  48 + end
  49 + rescue
  50 + options[:only] = Array.wrap(params[:fields])
  51 + end
  52 + end
  53 + present model, options
  54 + end
  55 +
42 56 include FindByContents
43 57  
44 58 ####################################################################
... ... @@ -99,12 +113,12 @@ require_relative &#39;../../find_by_contents&#39;
99 113 if !article.save
100 114 render_api_errors!(article.errors.full_messages)
101 115 end
102   - present article, :with => Entities::Article, :fields => params[:fields]
  116 + present_partial article, :with => Entities::Article
103 117 end
104 118  
105 119 def present_article(asset)
106 120 article = find_article(asset.articles, params[:id])
107   - present article, :with => Entities::Article, :fields => params[:fields]
  121 + present_partial article, :with => Entities::Article
108 122 end
109 123  
110 124 def present_articles_for_asset(asset, method = 'articles')
... ... @@ -113,12 +127,12 @@ require_relative &#39;../../find_by_contents&#39;
113 127 end
114 128  
115 129 def present_articles(articles)
116   - present articles, :with => Entities::Article, :fields => params[:fields]
  130 + present_partial articles, :with => Entities::Article
117 131 end
118 132  
119 133 def present_articles_paginated(articles, per_page=nil)
120 134 articles = paginate(articles)
121   - present articles, :with => Entities::Article, :fields => params[:fields]
  135 + present_partial articles, :with => Entities::Article
122 136 end
123 137  
124 138 def find_articles(asset, method = 'articles')
... ... @@ -148,19 +162,19 @@ require_relative &#39;../../find_by_contents&#39;
148 162 if !task.save
149 163 render_api_errors!(task.errors.full_messages)
150 164 end
151   - present task, :with => Entities::Task, :fields => params[:fields]
  165 + present_partial task, :with => Entities::Task
152 166 end
153 167  
154 168 def present_task(asset)
155 169 task = find_task(asset, params[:id])
156   - present task, :with => Entities::Task, :fields => params[:fields]
  170 + present_partial task, :with => Entities::Task
157 171 end
158 172  
159 173 def present_tasks(asset)
160 174 tasks = select_filtered_collection_of(asset, 'tasks', params)
161 175 tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)}
162 176 return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset)
163   - present tasks, :with => Entities::Task, :fields => params[:fields]
  177 + present_partial tasks, :with => Entities::Task
164 178 end
165 179  
166 180 def make_conditions_with_parameter(params = {})
... ...
lib/noosfero/api/v1/articles.rb
... ... @@ -58,7 +58,7 @@ module Noosfero
58 58 article = environment.articles.find(params[:id])
59 59 return forbidden! unless article.allow_edit?(current_person)
60 60 article.update_attributes!(params[:article])
61   - present article, :with => Entities::Article, :fields => params[:fields]
  61 + present_partial article, :with => Entities::Article
62 62 end
63 63  
64 64 desc 'Report a abuse and/or violent content in a article by id' do
... ... @@ -190,7 +190,7 @@ module Noosfero
190 190 article = find_article(environment.articles, params[:id])
191 191 child = find_article(article.children, params[:child_id])
192 192 child.hit
193   - present child, :with => Entities::Article, :fields => params[:fields]
  193 + present_partial child, :with => Entities::Article
194 194 end
195 195  
196 196 desc 'Suggest a article to another profile' do
... ... @@ -213,7 +213,7 @@ module Noosfero
213 213 unless suggest_article.save
214 214 render_api_errors!(suggest_article.article_object.errors.full_messages)
215 215 end
216   - present suggest_article, :with => Entities::Task, :fields => params[:fields]
  216 + present_partial suggest_article, :with => Entities::Task
217 217 end
218 218  
219 219 # Example Request:
... ... @@ -244,7 +244,7 @@ module Noosfero
244 244 if !article.save
245 245 render_api_errors!(article.errors.full_messages)
246 246 end
247   - present article, :with => Entities::Article, :fields => params[:fields]
  247 + present_partial article, :with => Entities::Article
248 248 end
249 249  
250 250 end
... ... @@ -271,7 +271,7 @@ module Noosfero
271 271 article = forbidden!
272 272 end
273 273  
274   - present article, :with => Entities::Article, :fields => params[:fields]
  274 + present_partial article, :with => Entities::Article
275 275 else
276 276  
277 277 present_articles_for_asset(profile)
... ...
lib/noosfero/api/v1/people.rb
... ... @@ -33,12 +33,12 @@ module Noosfero
33 33 get do
34 34 people = select_filtered_collection_of(environment, 'people', params)
35 35 people = people.visible_for_person(current_person)
36   - present people, :with => Entities::Person, :fields => params[:fields]
  36 + present_partial people, :with => Entities::Person
37 37 end
38 38  
39 39 desc "Return the logged user information"
40 40 get "/me" do
41   - present current_person, :with => Entities::Person, :fields => params[:fields]
  41 + present_partial current_person, :with => Entities::Person
42 42 end
43 43  
44 44 desc "Return the person information"
... ...
lib/noosfero/api/v1/tasks.rb
... ... @@ -20,13 +20,13 @@ module Noosfero
20 20 get do
21 21 tasks = select_filtered_collection_of(environment, 'tasks', params)
22 22 tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)}
23   - present tasks, :with => Entities::Task, :fields => params[:fields]
  23 + present_partial tasks, :with => Entities::Task
24 24 end
25 25  
26 26 desc "Return the task id"
27 27 get ':id' do
28 28 task = find_task(environment, params[:id])
29   - present task, :with => Entities::Task, :fields => params[:fields]
  29 + present_partial task, :with => Entities::Task
30 30 end
31 31 end
32 32  
... ...
test/unit/api/helpers_test.rb
... ... @@ -214,6 +214,26 @@ class APIHelpersTest &lt; ActiveSupport::TestCase
214 214 #assert_equals [article1, article2], present_articles
215 215 end
216 216  
  217 + should 'not touch in options when no fields parameter is passed' do
  218 + model = mock
  219 + expects(:present).with(model, {})
  220 + present_partial(model, {})
  221 + end
  222 +
  223 + should 'fallback to array when fields parameter is not a json when calling present partial' do
  224 + model = mock
  225 + params[:fields] = 'name'
  226 + expects(:present).with(model, {:only => ['name']})
  227 + present_partial(model, {})
  228 + end
  229 +
  230 + should 'accept json as fields parameter when calling present partial' do
  231 + model = mock
  232 + params[:fields] = {only: [:name, {user: [:login]}]}.to_json
  233 + expects(:present).with(model, {:only => ['name', {'user' => ['login']}]})
  234 + present_partial(model, {})
  235 + end
  236 +
217 237 ###### Captcha tests ######
218 238  
219 239 should 'do not test captcha when there are no settings' do
... ...
test/unit/api/people_test.rb
... ... @@ -54,6 +54,14 @@ class PeopleTest &lt; ActiveSupport::TestCase
54 54 assert_equal expected, json
55 55 end
56 56  
  57 + should 'people endpoint filter by fields parameter with hierarchy' do
  58 + fields = {only: [:name, {user: [:login]}]}.to_json
  59 + get "/api/v1/people?#{params.to_query}&fields=#{fields}"
  60 + json = JSON.parse(last_response.body)
  61 + expected = {'people' => [{'name' => person.name, 'user' => {'login' => 'testapi'}}]}
  62 + assert_equal expected, json
  63 + end
  64 +
57 65  
58 66 should 'get logged person' do
59 67 get "/api/v1/people/me?#{params.to_query}"
... ... @@ -184,13 +192,13 @@ class PeopleTest &lt; ActiveSupport::TestCase
184 192  
185 193 PERSON_ATTRIBUTES.map do |attribute|
186 194  
187   - define_method "test_should_not_expose_#{attribute}_attribute_in_person_enpoint_if_field_parameter_is_not_passed" do
188   - get "/api/v1/people/me?#{params.to_query}"
  195 + define_method "test_should_not_expose_#{attribute}_attribute_in_person_enpoint_if_field_parameter_does_not_contain_the_attribute" do
  196 + get "/api/v1/people/me?#{params.to_query}&fields=name"
189 197 json = JSON.parse(last_response.body)
190 198 assert_nil json['person'][attribute]
191 199 end
192 200  
193   - define_method "test_should_expose_#{attribute}_attribute_in_person_enpoints_only_if_field_parameter_is_passed" do
  201 + define_method "test_should_expose_#{attribute}_attribute_in_person_enpoints_if_field_parameter_is_passed" do
194 202 get "/api/v1/people/me?#{params.to_query}&fields=#{attribute}"
195 203 json = JSON.parse(last_response.body)
196 204 assert_not_nil json['person'][attribute]
... ...