Commit 56f3aee23b7ebc5092f0d48b8dbddffb1785bba3
1 parent
92fbfd94
Exists in
theme-brasil-digital-from-staging
and in
4 other branches
api: better support to choose returned fields
Showing
8 changed files
with
65 additions
and
37 deletions
Show diff stats
lib/noosfero/api/entities.rb
| @@ -96,14 +96,14 @@ module Noosfero | @@ -96,14 +96,14 @@ module Noosfero | ||
| 96 | class Person < Profile | 96 | class Person < Profile |
| 97 | root 'people', 'person' | 97 | root 'people', 'person' |
| 98 | expose :user, :using => UserBasic, documentation: {type: 'User', desc: 'The user data of a person' } | 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 | person.comments.count | 101 | person.comments.count |
| 102 | end | 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 | person.following_articles.count | 104 | person.following_articles.count |
| 105 | end | 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 | person.articles.count | 107 | person.articles.count |
| 108 | end | 108 | end |
| 109 | 109 |
lib/noosfero/api/entity.rb
| @@ -22,18 +22,4 @@ class Noosfero::API::Entity < Grape::Entity | @@ -22,18 +22,4 @@ class Noosfero::API::Entity < Grape::Entity | ||
| 22 | end | 22 | end |
| 23 | end | 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 | end | 25 | end |
lib/noosfero/api/helpers.rb
| @@ -39,6 +39,20 @@ require_relative '../../find_by_contents' | @@ -39,6 +39,20 @@ require_relative '../../find_by_contents' | ||
| 39 | @environment | 39 | @environment |
| 40 | end | 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 | include FindByContents | 56 | include FindByContents |
| 43 | 57 | ||
| 44 | #################################################################### | 58 | #################################################################### |
| @@ -99,12 +113,12 @@ require_relative '../../find_by_contents' | @@ -99,12 +113,12 @@ require_relative '../../find_by_contents' | ||
| 99 | if !article.save | 113 | if !article.save |
| 100 | render_api_errors!(article.errors.full_messages) | 114 | render_api_errors!(article.errors.full_messages) |
| 101 | end | 115 | end |
| 102 | - present article, :with => Entities::Article, :fields => params[:fields] | 116 | + present_partial article, :with => Entities::Article |
| 103 | end | 117 | end |
| 104 | 118 | ||
| 105 | def present_article(asset) | 119 | def present_article(asset) |
| 106 | article = find_article(asset.articles, params[:id]) | 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 | end | 122 | end |
| 109 | 123 | ||
| 110 | def present_articles_for_asset(asset, method = 'articles') | 124 | def present_articles_for_asset(asset, method = 'articles') |
| @@ -113,12 +127,12 @@ require_relative '../../find_by_contents' | @@ -113,12 +127,12 @@ require_relative '../../find_by_contents' | ||
| 113 | end | 127 | end |
| 114 | 128 | ||
| 115 | def present_articles(articles) | 129 | def present_articles(articles) |
| 116 | - present articles, :with => Entities::Article, :fields => params[:fields] | 130 | + present_partial articles, :with => Entities::Article |
| 117 | end | 131 | end |
| 118 | 132 | ||
| 119 | def present_articles_paginated(articles, per_page=nil) | 133 | def present_articles_paginated(articles, per_page=nil) |
| 120 | articles = paginate(articles) | 134 | articles = paginate(articles) |
| 121 | - present articles, :with => Entities::Article, :fields => params[:fields] | 135 | + present_partial articles, :with => Entities::Article |
| 122 | end | 136 | end |
| 123 | 137 | ||
| 124 | def find_articles(asset, method = 'articles') | 138 | def find_articles(asset, method = 'articles') |
| @@ -148,19 +162,19 @@ require_relative '../../find_by_contents' | @@ -148,19 +162,19 @@ require_relative '../../find_by_contents' | ||
| 148 | if !task.save | 162 | if !task.save |
| 149 | render_api_errors!(task.errors.full_messages) | 163 | render_api_errors!(task.errors.full_messages) |
| 150 | end | 164 | end |
| 151 | - present task, :with => Entities::Task, :fields => params[:fields] | 165 | + present_partial task, :with => Entities::Task |
| 152 | end | 166 | end |
| 153 | 167 | ||
| 154 | def present_task(asset) | 168 | def present_task(asset) |
| 155 | task = find_task(asset, params[:id]) | 169 | task = find_task(asset, params[:id]) |
| 156 | - present task, :with => Entities::Task, :fields => params[:fields] | 170 | + present_partial task, :with => Entities::Task |
| 157 | end | 171 | end |
| 158 | 172 | ||
| 159 | def present_tasks(asset) | 173 | def present_tasks(asset) |
| 160 | tasks = select_filtered_collection_of(asset, 'tasks', params) | 174 | tasks = select_filtered_collection_of(asset, 'tasks', params) |
| 161 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} | 175 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, asset)} |
| 162 | return forbidden! if tasks.empty? && !current_person.has_permission?(:perform_task, asset) | 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 | end | 178 | end |
| 165 | 179 | ||
| 166 | def make_conditions_with_parameter(params = {}) | 180 | def make_conditions_with_parameter(params = {}) |
lib/noosfero/api/v1/articles.rb
| @@ -58,7 +58,7 @@ module Noosfero | @@ -58,7 +58,7 @@ module Noosfero | ||
| 58 | article = environment.articles.find(params[:id]) | 58 | article = environment.articles.find(params[:id]) |
| 59 | return forbidden! unless article.allow_edit?(current_person) | 59 | return forbidden! unless article.allow_edit?(current_person) |
| 60 | article.update_attributes!(params[:article]) | 60 | article.update_attributes!(params[:article]) |
| 61 | - present article, :with => Entities::Article, :fields => params[:fields] | 61 | + present_partial article, :with => Entities::Article |
| 62 | end | 62 | end |
| 63 | 63 | ||
| 64 | desc 'Report a abuse and/or violent content in a article by id' do | 64 | desc 'Report a abuse and/or violent content in a article by id' do |
| @@ -190,7 +190,7 @@ module Noosfero | @@ -190,7 +190,7 @@ module Noosfero | ||
| 190 | article = find_article(environment.articles, params[:id]) | 190 | article = find_article(environment.articles, params[:id]) |
| 191 | child = find_article(article.children, params[:child_id]) | 191 | child = find_article(article.children, params[:child_id]) |
| 192 | child.hit | 192 | child.hit |
| 193 | - present child, :with => Entities::Article, :fields => params[:fields] | 193 | + present_partial child, :with => Entities::Article |
| 194 | end | 194 | end |
| 195 | 195 | ||
| 196 | desc 'Suggest a article to another profile' do | 196 | desc 'Suggest a article to another profile' do |
| @@ -213,7 +213,7 @@ module Noosfero | @@ -213,7 +213,7 @@ module Noosfero | ||
| 213 | unless suggest_article.save | 213 | unless suggest_article.save |
| 214 | render_api_errors!(suggest_article.article_object.errors.full_messages) | 214 | render_api_errors!(suggest_article.article_object.errors.full_messages) |
| 215 | end | 215 | end |
| 216 | - present suggest_article, :with => Entities::Task, :fields => params[:fields] | 216 | + present_partial suggest_article, :with => Entities::Task |
| 217 | end | 217 | end |
| 218 | 218 | ||
| 219 | # Example Request: | 219 | # Example Request: |
| @@ -244,7 +244,7 @@ module Noosfero | @@ -244,7 +244,7 @@ module Noosfero | ||
| 244 | if !article.save | 244 | if !article.save |
| 245 | render_api_errors!(article.errors.full_messages) | 245 | render_api_errors!(article.errors.full_messages) |
| 246 | end | 246 | end |
| 247 | - present article, :with => Entities::Article, :fields => params[:fields] | 247 | + present_partial article, :with => Entities::Article |
| 248 | end | 248 | end |
| 249 | 249 | ||
| 250 | end | 250 | end |
| @@ -271,7 +271,7 @@ module Noosfero | @@ -271,7 +271,7 @@ module Noosfero | ||
| 271 | article = forbidden! | 271 | article = forbidden! |
| 272 | end | 272 | end |
| 273 | 273 | ||
| 274 | - present article, :with => Entities::Article, :fields => params[:fields] | 274 | + present_partial article, :with => Entities::Article |
| 275 | else | 275 | else |
| 276 | 276 | ||
| 277 | present_articles_for_asset(profile) | 277 | present_articles_for_asset(profile) |
lib/noosfero/api/v1/people.rb
| @@ -33,12 +33,12 @@ module Noosfero | @@ -33,12 +33,12 @@ module Noosfero | ||
| 33 | get do | 33 | get do |
| 34 | people = select_filtered_collection_of(environment, 'people', params) | 34 | people = select_filtered_collection_of(environment, 'people', params) |
| 35 | people = people.visible_for_person(current_person) | 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 | end | 37 | end |
| 38 | 38 | ||
| 39 | desc "Return the logged user information" | 39 | desc "Return the logged user information" |
| 40 | get "/me" do | 40 | get "/me" do |
| 41 | - present current_person, :with => Entities::Person, :fields => params[:fields] | 41 | + present_partial current_person, :with => Entities::Person |
| 42 | end | 42 | end |
| 43 | 43 | ||
| 44 | desc "Return the person information" | 44 | desc "Return the person information" |
lib/noosfero/api/v1/tasks.rb
| @@ -20,13 +20,13 @@ module Noosfero | @@ -20,13 +20,13 @@ module Noosfero | ||
| 20 | get do | 20 | get do |
| 21 | tasks = select_filtered_collection_of(environment, 'tasks', params) | 21 | tasks = select_filtered_collection_of(environment, 'tasks', params) |
| 22 | tasks = tasks.select {|t| current_person.has_permission?(t.permission, environment)} | 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 | end | 24 | end |
| 25 | 25 | ||
| 26 | desc "Return the task id" | 26 | desc "Return the task id" |
| 27 | get ':id' do | 27 | get ':id' do |
| 28 | task = find_task(environment, params[:id]) | 28 | task = find_task(environment, params[:id]) |
| 29 | - present task, :with => Entities::Task, :fields => params[:fields] | 29 | + present_partial task, :with => Entities::Task |
| 30 | end | 30 | end |
| 31 | end | 31 | end |
| 32 | 32 |
test/unit/api/helpers_test.rb
| @@ -214,6 +214,26 @@ class APIHelpersTest < ActiveSupport::TestCase | @@ -214,6 +214,26 @@ class APIHelpersTest < ActiveSupport::TestCase | ||
| 214 | #assert_equals [article1, article2], present_articles | 214 | #assert_equals [article1, article2], present_articles |
| 215 | end | 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 | ###### Captcha tests ###### | 237 | ###### Captcha tests ###### |
| 218 | 238 | ||
| 219 | should 'do not test captcha when there are no settings' do | 239 | should 'do not test captcha when there are no settings' do |
test/unit/api/people_test.rb
| @@ -54,6 +54,14 @@ class PeopleTest < ActiveSupport::TestCase | @@ -54,6 +54,14 @@ class PeopleTest < ActiveSupport::TestCase | ||
| 54 | assert_equal expected, json | 54 | assert_equal expected, json |
| 55 | end | 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 | should 'get logged person' do | 66 | should 'get logged person' do |
| 59 | get "/api/v1/people/me?#{params.to_query}" | 67 | get "/api/v1/people/me?#{params.to_query}" |
| @@ -184,13 +192,13 @@ class PeopleTest < ActiveSupport::TestCase | @@ -184,13 +192,13 @@ class PeopleTest < ActiveSupport::TestCase | ||
| 184 | 192 | ||
| 185 | PERSON_ATTRIBUTES.map do |attribute| | 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 | json = JSON.parse(last_response.body) | 197 | json = JSON.parse(last_response.body) |
| 190 | assert_nil json['person'][attribute] | 198 | assert_nil json['person'][attribute] |
| 191 | end | 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 | get "/api/v1/people/me?#{params.to_query}&fields=#{attribute}" | 202 | get "/api/v1/people/me?#{params.to_query}&fields=#{attribute}" |
| 195 | json = JSON.parse(last_response.body) | 203 | json = JSON.parse(last_response.body) |
| 196 | assert_not_nil json['person'][attribute] | 204 | assert_not_nil json['person'][attribute] |