json_api_client-legacy 1.0.0.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db01b6871d441bfbeb6088d8adfdb01f2aa3650c
4
+ data.tar.gz: 764f2a807a96b1a6f7724fe703279f5941340f35
5
+ SHA512:
6
+ metadata.gz: 0b706948566acbd5e7dbfb65dd5361d0713d33f893339c3b602b51b800a5fec6958a3d87b1c02369def8905d180b7597a98cb9ac86c76085050b48f2fab014f2
7
+ data.tar.gz: 422aa93b68cf1c6bf6f68e11449798dcfa8cd9fa2ca4ec5fd64922a1005e7893034ccb662628fe01fefc00c17522f842cd34503ca05755ebc4e1579408372428
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.1
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in json_api_client-legacy.gemspec
4
+ gemspec
5
+
6
+ gem "json_api_client"
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # JsonApiClient::Legacy
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/json_api_client/legacy`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'json_api_client-legacy'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install json_api_client-legacy
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ 1. Fork it ( https://github.com/[my-github-username]/json_api_client-legacy/fork )
36
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
37
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
38
+ 4. Push to the branch (`git push origin my-new-feature`)
39
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new(:test) do |t|
6
+ t.libs << 'lib'
7
+ t.libs << 'test'
8
+ t.pattern = 'test/**/*_test.rb'
9
+ t.verbose = false
10
+ end
11
+
12
+
13
+ task default: :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "json_api_client/legacy"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'json_api_client/legacy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "json_api_client-legacy"
8
+ spec.version = JsonApiClient::Legacy::VERSION
9
+ spec.authors = ["Jeff Ching"]
10
+ spec.email = ["ching.jeff@gmail.com"]
11
+
12
+ spec.summary = %q{Customizations for json_api_client 1.0.0 to handle 0.x servers}
13
+ spec.description = %q{Customizations for json_api_client 1.0.0 to handle 0.x servers}
14
+ spec.homepage = "https://github.com/chingor13/json_api_client-legacy"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "json_api_client", "~> 1.0.0.beta"
22
+
23
+ spec.add_development_dependency "bundler"
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_development_dependency "webmock"
26
+ spec.add_development_dependency "mocha"
27
+ end
@@ -0,0 +1 @@
1
+ require 'json_api_client/legacy'
@@ -0,0 +1,16 @@
1
+ require "json_api_client"
2
+ require "json_api_client/legacy/version"
3
+
4
+ module JsonApiClient
5
+ module Legacy
6
+ autoload :Base, "json_api_client/legacy/base"
7
+ autoload :Connection, "json_api_client/legacy/connection"
8
+ autoload :LinkDefinition, "json_api_client/legacy/link_definition"
9
+ autoload :LinkedData, "json_api_client/legacy/linked_data"
10
+ autoload :Linker, "json_api_client/legacy/linker"
11
+ autoload :Paginator, "json_api_client/legacy/paginator"
12
+ autoload :Parser, "json_api_client/legacy/parser"
13
+ autoload :QueryBuilder, "json_api_client/legacy/query_builder"
14
+ autoload :Requestor, "json_api_client/legacy/requestor"
15
+ end
16
+ end
@@ -0,0 +1,18 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class Base < Resource
4
+ self.connection_class = JsonApiClient::Legacy::Connection
5
+ self.linker = JsonApiClient::Legacy::Linker
6
+ self.parser = JsonApiClient::Legacy::Parser
7
+ self.paginator = JsonApiClient::Legacy::Paginator
8
+ self.query_builder = JsonApiClient::Legacy::QueryBuilder
9
+ self.requestor_class = JsonApiClient::Legacy::Requestor
10
+
11
+ protected
12
+
13
+ def self.default_attributes
14
+ {}
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,35 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class Connection
4
+
5
+ attr_reader :faraday
6
+
7
+ def initialize(options = {})
8
+ site = options.fetch(:site)
9
+ @faraday = Faraday.new(site) do |builder|
10
+ builder.request :json
11
+ builder.use Middleware::Status
12
+ builder.use Middleware::ParseJson
13
+ builder.adapter Faraday.default_adapter
14
+ end
15
+ yield(self) if block_given?
16
+ end
17
+
18
+ # insert middleware before ParseJson - middleware executed in reverse order -
19
+ # inserted middleware will run after json parsed
20
+ def use(middleware, *args, &block)
21
+ return if faraday.builder.locked?
22
+ faraday.builder.insert_before(Middleware::ParseJson, middleware, *args, &block)
23
+ end
24
+
25
+ def delete(middleware)
26
+ faraday.builder.delete(middleware)
27
+ end
28
+
29
+ def run(request_method, path, params = {}, headers = {})
30
+ faraday.send(request_method, path, params, headers)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class LinkDefinition
4
+
5
+ def initialize(spec)
6
+ @spec = {}.with_indifferent_access
7
+ spec.each do |type, definition|
8
+ @spec[type.split(".").last] = definition.merge({slurp: type})
9
+ end
10
+ end
11
+
12
+ def has_link?(type)
13
+ @spec.has_key?(type)
14
+ end
15
+
16
+ def attribute_name_for(type)
17
+ @spec.fetch(type).fetch("type")
18
+ end
19
+
20
+ def url_for(type, ids)
21
+ definition = @spec.fetch(type)
22
+ href = definition.fetch("href")
23
+ slurp = definition.fetch("slurp")
24
+ href.gsub("{#{slurp}}", Array(ids).join(","))
25
+ end
26
+
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,69 @@
1
+ # This object holds the preloaded data from the json response - essentially
2
+ # the preloaded foreign keys
3
+ module JsonApiClient
4
+ module Legacy
5
+ class LinkedData
6
+ attr_reader :link_definition,
7
+ :record_class
8
+
9
+ extend Forwardable
10
+ def_delegators :link_definition, :has_link?
11
+
12
+ def initialize(data, link_definition, record_class)
13
+ @link_definition = link_definition
14
+ @record_class = record_class
15
+ @results_by_type_by_id = {}
16
+
17
+ data.each do |type, results|
18
+ klass = klass_for(type)
19
+ add_data(type, results.map{|result| klass.new(result)})
20
+ end
21
+ end
22
+
23
+ def data_for(type, ids)
24
+ ids = Array(ids)
25
+
26
+ # the name of the linked data is provided by the link definition from the result
27
+ attr_name = link_definition.attribute_name_for(type)
28
+
29
+ # get any preloaded data from the result
30
+ type_data = @results_by_type_by_id.fetch(attr_name, {})
31
+
32
+ # find the associated class for the data
33
+ klass = klass_for(type)
34
+
35
+ # return all the found records
36
+ found, missing = ids.partition { |id| type_data[id].present? }
37
+
38
+ # make another api request if there are missing records
39
+ fetch_data(klass, type, missing) if missing.present?
40
+
41
+ # reload data
42
+ type_data = @results_by_type_by_id.fetch(attr_name, {})
43
+
44
+ ids.map do |id|
45
+ type_data[id]
46
+ end
47
+ end
48
+
49
+ # make an api request to fetch the missing data
50
+ def fetch_data(klass, type, missing_ids)
51
+ path = URI(link_definition.url_for(type, missing_ids)).path
52
+
53
+ results = klass.requestor.linked(path)
54
+
55
+ key = link_definition.attribute_name_for(type).to_s
56
+ add_data(key, results)
57
+ end
58
+
59
+ def add_data(key, data)
60
+ @results_by_type_by_id[key] ||= {}
61
+ @results_by_type_by_id[key].merge!(data.index_by{|datum| datum["id"]})
62
+ end
63
+
64
+ def klass_for(type)
65
+ Utils.compute_type(record_class, type.to_s.pluralize.classify)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,16 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class Linker
4
+ include Helpers::DynamicAttributes
5
+
6
+ def initialize(links)
7
+ self.attributes = links
8
+ end
9
+
10
+ def present?
11
+ attributes.present?
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,71 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class Paginator
4
+ attr_reader :meta, :result_set
5
+ def initialize(result_set, meta)
6
+ @meta = meta
7
+ @result_set = result_set
8
+ end
9
+
10
+ def next
11
+ raise NotImplementedError
12
+ end
13
+
14
+ def prev
15
+ raise NotImplementedError
16
+ end
17
+
18
+ def first
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def last
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def total_pages
27
+ meta.fetch("total_pages") do
28
+ (1.0 * total_entries / per_page).ceil rescue 1
29
+ end
30
+ end
31
+
32
+ def total_entries
33
+ meta.fetch("total_entries") do
34
+ result_set.length
35
+ end
36
+ end
37
+
38
+ def offset
39
+ meta.fetch("offset") do
40
+ per_page * (current_page - 1)
41
+ end
42
+ end
43
+
44
+ def per_page
45
+ meta.fetch("per_page") do
46
+ result_set.length
47
+ end
48
+ end
49
+
50
+ def current_page
51
+ meta.fetch("current_page") do
52
+ meta.fetch("page", 1)
53
+ end
54
+ end
55
+
56
+ def out_of_bounds?
57
+ current_page > total_pages
58
+ end
59
+
60
+ def previous_page
61
+ current_page > 1 ? (current_page - 1) : nil
62
+ end
63
+
64
+ def next_page
65
+ current_page < total_pages ? (current_page + 1) : nil
66
+ end
67
+
68
+ alias limit_value per_page
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,61 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class Parser
4
+
5
+ class << self
6
+ def parse(klass, response)
7
+ data = response.body
8
+ ResultSet.new.tap do |result_set|
9
+ result_set.record_class = klass
10
+ result_set.uri = response.env[:url]
11
+ handle_data(result_set, data)
12
+ handle_meta(result_set, data)
13
+ handle_pagination(result_set, data)
14
+ handle_links(result_set, data)
15
+ handle_errors(result_set, data)
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def handle_data(result_set, data)
22
+ # data can live under the table name or the generic "data" key
23
+ results = data.fetch(result_set.record_class.table_name) do
24
+ results.fetch("data", [])
25
+ end
26
+
27
+ # we will treat everything as an Array
28
+ results = [results] unless results.is_a?(Array)
29
+ result_set.concat(results.map{|res| result_set.record_class.load(res)})
30
+ end
31
+
32
+ def handle_meta(result_set, data)
33
+ result_set.meta = data.fetch("meta", {})
34
+ end
35
+
36
+ def handle_pagination(result_set, data)
37
+ result_set.pages = result_set.record_class.paginator.new(result_set, result_set.meta)
38
+ end
39
+
40
+ def handle_links(result_set, data)
41
+ return if result_set.empty?
42
+
43
+ linked_data = LinkedData.new(
44
+ data.fetch("linked", {}),
45
+ LinkDefinition.new(data.fetch("links", {})),
46
+ result_set.record_class
47
+ )
48
+
49
+ result_set.each do |resource|
50
+ resource.linked_data = linked_data
51
+ end
52
+ end
53
+
54
+ def handle_errors(result_set, data)
55
+ result_set.errors = result_set.meta.fetch("errors", [])
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,51 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class QueryBuilder
4
+
5
+ attr_reader :klass, :params
6
+
7
+ def initialize(klass)
8
+ @klass = klass
9
+ @params = {}
10
+ end
11
+
12
+ def where(conditions = {})
13
+ @params.merge!(conditions)
14
+ self
15
+ end
16
+ alias paginate where
17
+
18
+ def order(conditions)
19
+ where(order: conditions)
20
+ end
21
+
22
+ def includes(*tables)
23
+ @params[:includes] ||= []
24
+ @params[:includes] += tables.flatten
25
+ self
26
+ end
27
+
28
+ def page(number)
29
+ where(page: number)
30
+ end
31
+
32
+ def first
33
+ paginate(page: 1, per_page: 1).to_a.first
34
+ end
35
+
36
+ def build
37
+ klass.new(params)
38
+ end
39
+
40
+ def to_a
41
+ @to_a ||= klass.find(params)
42
+ end
43
+ alias all to_a
44
+
45
+ def method_missing(method_name, *args, &block)
46
+ to_a.send(method_name, *args, &block)
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,77 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ class Requestor
4
+ extend Forwardable
5
+
6
+ def initialize(klass)
7
+ @klass = klass
8
+ end
9
+
10
+ # expects a record
11
+ def create(record)
12
+ request(:post, klass.path(record.attributes), {
13
+ klass.resource_name => record.attributes
14
+ })
15
+ end
16
+
17
+ def update(record)
18
+ request(:put, resource_path(record.attributes), {
19
+ klass.resource_name => record.attributes.except(klass.primary_key)
20
+ })
21
+ end
22
+
23
+ def find(args)
24
+ params = case args
25
+ when Hash
26
+ args
27
+ when Array
28
+ {klass.primary_key.to_s.pluralize.to_sym => args.join(",")}
29
+ else
30
+ {klass.primary_key => args}
31
+ end
32
+
33
+ path = resource_path(params)
34
+ params.delete(klass.primary_key)
35
+ request(:get, path, params)
36
+ end
37
+
38
+ def destroy(record)
39
+ request(:delete, resource_path(record.attributes), {})
40
+ end
41
+
42
+ def linked(path)
43
+ request(:get, path, {})
44
+ end
45
+
46
+ def custom(method_name, options, params)
47
+ path = resource_path(params)
48
+ params.delete(klass.primary_key)
49
+ path = File.join(path, method_name.to_s)
50
+
51
+ request(options.fetch(:request_method, :get), path, params)
52
+ end
53
+
54
+ protected
55
+
56
+ attr_reader :klass
57
+ def_delegators :klass, :connection
58
+
59
+ def resource_path(parameters)
60
+ if resource_id = parameters[klass.primary_key]
61
+ File.join(klass.path(parameters), encoded(resource_id))
62
+ else
63
+ klass.path(parameters)
64
+ end
65
+ end
66
+
67
+ def encoded(part)
68
+ Addressable::URI.encode_component(part, Addressable::URI::CharacterClasses::UNRESERVED)
69
+ end
70
+
71
+ def request(type, path, params)
72
+ klass.parse(connection.run(type, path, params))
73
+ end
74
+
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,5 @@
1
+ module JsonApiClient
2
+ module Legacy
3
+ VERSION = "1.0.0.beta"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: json_api_client-legacy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0.beta
5
+ platform: ruby
6
+ authors:
7
+ - Jeff Ching
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-05-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: json_api_client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 1.0.0.beta
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 1.0.0.beta
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: mocha
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Customizations for json_api_client 1.0.0 to handle 0.x servers
84
+ email:
85
+ - ching.jeff@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - README.md
94
+ - Rakefile
95
+ - bin/console
96
+ - bin/setup
97
+ - json_api_client-legacy.gemspec
98
+ - lib/json_api_client-legacy.rb
99
+ - lib/json_api_client/legacy.rb
100
+ - lib/json_api_client/legacy/base.rb
101
+ - lib/json_api_client/legacy/connection.rb
102
+ - lib/json_api_client/legacy/link_definition.rb
103
+ - lib/json_api_client/legacy/linked_data.rb
104
+ - lib/json_api_client/legacy/linker.rb
105
+ - lib/json_api_client/legacy/paginator.rb
106
+ - lib/json_api_client/legacy/parser.rb
107
+ - lib/json_api_client/legacy/query_builder.rb
108
+ - lib/json_api_client/legacy/requestor.rb
109
+ - lib/json_api_client/legacy/version.rb
110
+ homepage: https://github.com/chingor13/json_api_client-legacy
111
+ licenses: []
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">"
125
+ - !ruby/object:Gem::Version
126
+ version: 1.3.1
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.2.2
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Customizations for json_api_client 1.0.0 to handle 0.x servers
133
+ test_files: []
134
+ has_rdoc: