From 5b4935e518f964ce439558eae30217da836eca29 Mon Sep 17 00:00:00 2001 From: Sam Goldman Date: Fri, 21 Jul 2017 14:14:03 -0400 Subject: [PATCH] allows sparse fieldsets for multiple resources --- README.md | 6 ++++- lib/json_api_client/query/builder.rb | 39 +++++++++++++++++++++++----- test/unit/query_builder_test.rb | 37 ++++++++++++++++++++++++++ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 03fac9b3..7da07de0 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,10 @@ article.title # should not have returned the created_at article.created_at # => raise NoMethodError + +# or you can use fieldsets from multiple resources +# makes request to /articles?fields[articles]=title,body&fields[comments]=tag +article = Article.select("title", "body",{comments: 'tag'}).first ``` ## Sorting @@ -485,7 +489,7 @@ class MyMoneyCaster end end end - + JsonApiClient::Schema.register money: MyMoneyCaster ``` diff --git a/lib/json_api_client/query/builder.rb b/lib/json_api_client/query/builder.rb index 2734c0ba..3494fc71 100644 --- a/lib/json_api_client/query/builder.rb +++ b/lib/json_api_client/query/builder.rb @@ -35,11 +35,7 @@ def includes(*tables) end def select(*fields) - fields = Array(fields).flatten - fields = fields.map { |i| i.to_s.split(",") }.flatten - - @fields += fields.map(&:strip) - + @fields += parse_fields(*fields) self end @@ -143,7 +139,23 @@ def order_params end def select_params - @fields.empty? ? {} : {fields: {klass.table_name => @fields.join(",")}} + if @fields.empty? + {} + else + field_result = Hash.new { |h,k| h[k] = [] } + @fields.each do |field| + if field.is_a? Hash + field.each do |k,v| + field_result[k.to_s] << v + field_result[k.to_s] = field_result[k.to_s].flatten + end + else + field_result[klass.table_name] << field + end + end + field_result.each { |k,v| field_result[k] = v.join(',') } + {fields: field_result} + end end def parse_related_links(*tables) @@ -179,6 +191,21 @@ def parse_orders(*args) end.flatten end + def parse_fields(*fields) + fields = fields.split(',') if fields.is_a? String + fields.map do |field| + case field + when Hash + field.each do |k,v| + field[k] = parse_fields(v) + end + field + else + Array(field).flatten.map { |i| i.to_s.split(",") }.flatten.map(&:strip) + end + end.flatten + end + end end end diff --git a/test/unit/query_builder_test.rb b/test/unit/query_builder_test.rb index 2bc5c314..217da75f 100644 --- a/test/unit/query_builder_test.rb +++ b/test/unit/query_builder_test.rb @@ -132,4 +132,41 @@ def test_can_select_fields_using_implicit_array Article.select(:title, :body).to_a end + def test_can_select_nested_fields_using_hashes + stub_request(:get, "http://example.com/articles") + .with(query: {fields: {articles: 'tags', comments: 'author'}}) + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [] + }.to_json) + Article.select({comments: :author}, :tags).to_a + end + + + def test_can_select_nested_fields_using_hashes_of_arrays + stub_request(:get, "http://example.com/articles") + .with(query: {fields: {articles: 'tags', comments: 'author,text'}}) + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [] + }.to_json) + Article.select({comments: [:author, :text]}, :tags).to_a + end + + def test_can_select_nested_fields_using_strings + stub_request(:get, "http://example.com/articles") + .with(query: {fields: {articles: 'tags', comments: 'author,text'}}) + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [] + }.to_json) + Article.select({comments: ['author', 'text']}, :tags).to_a + end + + def test_can_select_nested_fields_using_comma_separated_strings + stub_request(:get, "http://example.com/articles") + .with(query: {fields: {articles: 'tags', comments: 'author,text'}}) + .to_return(headers: {content_type: "application/vnd.api+json"}, body: { + data: [] + }.to_json) + Article.select({comments: 'author,text'}, :tags).to_a + end + end