test_track_rails_client 0.9.7 → 0.9.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +11 -8
- data/lib/test_track_rails_client/version.rb +1 -1
- data/vendor/gems/fakeable_her/fakeable_her.gemspec +22 -0
- data/vendor/gems/fakeable_her/lib/fakeable_her/model.rb +148 -0
- data/vendor/gems/fakeable_her/lib/fakeable_her/version.rb +3 -0
- data/vendor/gems/fakeable_her/lib/fakeable_her.rb +5 -0
- data/vendor/gems/her/CONTRIBUTING.md +26 -0
- data/vendor/gems/her/Gemfile +10 -0
- data/vendor/gems/her/LICENSE +7 -0
- data/vendor/gems/her/README.md +1023 -0
- data/vendor/gems/her/Rakefile +11 -0
- data/vendor/gems/her/UPGRADE.md +101 -0
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-3.2.x +7 -0
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.0 +7 -0
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.1 +7 -0
- data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.2 +7 -0
- data/vendor/gems/her/her.gemspec +31 -0
- data/vendor/gems/her/lib/her/api.rb +119 -0
- data/vendor/gems/her/lib/her/collection.rb +12 -0
- data/vendor/gems/her/lib/her/error_collection.rb +15 -0
- data/vendor/gems/her/lib/her/errors.rb +40 -0
- data/vendor/gems/her/lib/her/json_api/model.rb +46 -0
- data/vendor/gems/her/lib/her/middleware/accept_json.rb +17 -0
- data/vendor/gems/her/lib/her/middleware/first_level_parse_json.rb +36 -0
- data/vendor/gems/her/lib/her/middleware/json_api_parser.rb +36 -0
- data/vendor/gems/her/lib/her/middleware/parse_json.rb +21 -0
- data/vendor/gems/her/lib/her/middleware/second_level_parse_json.rb +36 -0
- data/vendor/gems/her/lib/her/middleware.rb +12 -0
- data/vendor/gems/her/lib/her/model/active_model_overrides.rb +13 -0
- data/vendor/gems/her/lib/her/model/associations/association.rb +106 -0
- data/vendor/gems/her/lib/her/model/associations/association_proxy.rb +46 -0
- data/vendor/gems/her/lib/her/model/associations/belongs_to_association.rb +96 -0
- data/vendor/gems/her/lib/her/model/associations/has_many_association.rb +100 -0
- data/vendor/gems/her/lib/her/model/associations/has_one_association.rb +79 -0
- data/vendor/gems/her/lib/her/model/associations.rb +141 -0
- data/vendor/gems/her/lib/her/model/attributes.rb +304 -0
- data/vendor/gems/her/lib/her/model/base.rb +33 -0
- data/vendor/gems/her/lib/her/model/deprecated_methods.rb +61 -0
- data/vendor/gems/her/lib/her/model/http.rb +117 -0
- data/vendor/gems/her/lib/her/model/introspection.rb +65 -0
- data/vendor/gems/her/lib/her/model/nested_attributes.rb +45 -0
- data/vendor/gems/her/lib/her/model/orm.rb +219 -0
- data/vendor/gems/her/lib/her/model/parse.rb +215 -0
- data/vendor/gems/her/lib/her/model/paths.rb +126 -0
- data/vendor/gems/her/lib/her/model/relation.rb +251 -0
- data/vendor/gems/her/lib/her/model.rb +81 -0
- data/vendor/gems/her/lib/her/version.rb +3 -0
- data/vendor/gems/her/lib/her.rb +20 -0
- data/vendor/gems/her/spec/api_spec.rb +114 -0
- data/vendor/gems/her/spec/collection_spec.rb +26 -0
- data/vendor/gems/her/spec/error_collection_spec.rb +33 -0
- data/vendor/gems/her/spec/json_api/model_spec.rb +168 -0
- data/vendor/gems/her/spec/middleware/accept_json_spec.rb +10 -0
- data/vendor/gems/her/spec/middleware/first_level_parse_json_spec.rb +62 -0
- data/vendor/gems/her/spec/middleware/json_api_parser_spec.rb +32 -0
- data/vendor/gems/her/spec/middleware/second_level_parse_json_spec.rb +35 -0
- data/vendor/gems/her/spec/model/associations/association_proxy_spec.rb +31 -0
- data/vendor/gems/her/spec/model/associations_spec.rb +504 -0
- data/vendor/gems/her/spec/model/attributes_spec.rb +404 -0
- data/vendor/gems/her/spec/model/callbacks_spec.rb +145 -0
- data/vendor/gems/her/spec/model/dirty_spec.rb +110 -0
- data/vendor/gems/her/spec/model/http_spec.rb +165 -0
- data/vendor/gems/her/spec/model/introspection_spec.rb +76 -0
- data/vendor/gems/her/spec/model/nested_attributes_spec.rb +134 -0
- data/vendor/gems/her/spec/model/orm_spec.rb +791 -0
- data/vendor/gems/her/spec/model/parse_spec.rb +372 -0
- data/vendor/gems/her/spec/model/paths_spec.rb +347 -0
- data/vendor/gems/her/spec/model/relation_spec.rb +226 -0
- data/vendor/gems/her/spec/model/validations_spec.rb +42 -0
- data/vendor/gems/her/spec/model_spec.rb +31 -0
- data/vendor/gems/her/spec/spec_helper.rb +27 -0
- data/vendor/gems/her/spec/support/extensions/array.rb +5 -0
- data/vendor/gems/her/spec/support/extensions/hash.rb +5 -0
- data/vendor/gems/her/spec/support/macros/her_macros.rb +17 -0
- data/vendor/gems/her/spec/support/macros/model_macros.rb +36 -0
- data/vendor/gems/her/spec/support/macros/request_macros.rb +27 -0
- data/vendor/gems/publicsuffix-ruby/CHANGELOG.md +236 -0
- data/vendor/gems/publicsuffix-ruby/Gemfile +3 -0
- data/vendor/gems/publicsuffix-ruby/LICENSE.txt +22 -0
- data/vendor/gems/publicsuffix-ruby/README.md +151 -0
- data/vendor/gems/publicsuffix-ruby/Rakefile +109 -0
- data/vendor/gems/publicsuffix-ruby/lib/definitions.txt +11467 -0
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/domain.rb +387 -0
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/errors.rb +53 -0
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/list.rb +302 -0
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/rule.rb +373 -0
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix/version.rb +23 -0
- data/vendor/gems/publicsuffix-ruby/lib/public_suffix.rb +131 -0
- data/vendor/gems/publicsuffix-ruby/public_suffix.gemspec +39 -0
- data/vendor/gems/publicsuffix-ruby/test/acceptance_test.rb +42 -0
- data/vendor/gems/publicsuffix-ruby/test/test_helper.rb +6 -0
- data/vendor/gems/publicsuffix-ruby/test/unit/domain_test.rb +170 -0
- data/vendor/gems/publicsuffix-ruby/test/unit/errors_test.rb +23 -0
- data/vendor/gems/publicsuffix-ruby/test/unit/list_test.rb +179 -0
- data/vendor/gems/publicsuffix-ruby/test/unit/public_suffix_test.rb +115 -0
- data/vendor/gems/publicsuffix-ruby/test/unit/rule_test.rb +307 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/capybara_configuration.rb +98 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/matchers.rb +151 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rspec_configuration.rb +34 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/html_safe.rb +15 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/raw.rb +15 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/safe_concat.rb +15 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop.rb +3 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples/betterment_application_examples.rb +47 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples.rb +1 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_configuration.rb +42 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_dropdown.rb +17 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/version.rb +3 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/webmock_configuration.rb +8 -0
- data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers.rb +2 -0
- data/vendor/gems/ruby_spec_helpers/ruby_spec_helpers.gemspec +25 -0
- metadata +110 -1
@@ -0,0 +1,101 @@
|
|
1
|
+
# Upgrade Her
|
2
|
+
|
3
|
+
Here is a list of notable changes by release. Her follows the [Semantic Versioning](http://semver.org/) system.
|
4
|
+
|
5
|
+
## 0.8.0
|
6
|
+
|
7
|
+
- Initial support for JSONAPI [link](https://github.com/remiprev/her/pull/347)
|
8
|
+
- Fix for has_one association parsing [link](https://github.com/remiprev/her/pull/352)
|
9
|
+
- Fix for escaping path variables HT @marshall-lee [link](https://github.com/remiprev/her/pull/354)
|
10
|
+
- Fix syntax highlighting in README HT @tippenein [link](https://github.com/remiprev/her/pull/356)
|
11
|
+
- Fix associations with Active Model Serializers HT @minktom [link](https://github.com/remiprev/her/pull/359)
|
12
|
+
|
13
|
+
## 0.7.6
|
14
|
+
|
15
|
+
- Loosen restrictions on ActiveSupport and ActiveModel to accommodate security fixes [link](https://github.com/remiprev/her/commit/8ff641fcdaf14be7cc9b1a6ee6654f27f7dfa34c)
|
16
|
+
|
17
|
+
## 0.7.5
|
18
|
+
|
19
|
+
- Performance fix for responses with large number of objects [link](https://github.com/remiprev/her/pull/337)
|
20
|
+
- Bugfix for dirty attributes [link](https://github.com/remiprev/her/commit/70285debc6837a33a3a750c7c4a7251439464b42)
|
21
|
+
- Add ruby 2.1 and 2.2 to travis test run. We will likely be removing official 1.9.x support in the near future, and
|
22
|
+
will begin to align our support with the official ruby maintenance schedule.
|
23
|
+
- README updates
|
24
|
+
|
25
|
+
## 0.6
|
26
|
+
|
27
|
+
Associations have been refactored so that calling the association name method doesn’t immediately load or fetch the data.
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
class User
|
31
|
+
include Her::Model
|
32
|
+
has_many :comments
|
33
|
+
end
|
34
|
+
|
35
|
+
# This doesn’t fetch the data yet and it’s still chainable
|
36
|
+
comments = User.find(1).comments
|
37
|
+
|
38
|
+
# This actually fetches the data
|
39
|
+
puts comments.inspect
|
40
|
+
|
41
|
+
# This is no longer possible in her-0.6
|
42
|
+
comments = User.find(1).comments(:approved => 1)
|
43
|
+
|
44
|
+
# To pass additional parameters to the HTTP request, we now have to do this
|
45
|
+
comments = User.find(1).comments.where(:approved => 1)
|
46
|
+
```
|
47
|
+
|
48
|
+
## 0.5
|
49
|
+
|
50
|
+
Her is now compatible with `ActiveModel` and includes `ActiveModel::Validations`.
|
51
|
+
|
52
|
+
Before 0.5, the `errors` method on an object would return an error list received from the server (the `:errors` key defined by the parsing middleware). But now, `errors` returns the error list generated after calling the `valid?` method (or any other similar validation method from `ActiveModel::Validations`). The error list returned from the server is now accessible from the `response_errors` method.
|
53
|
+
|
54
|
+
Since 0.5.5, Her provides a `store_response_errors` method, which allows you to choose the method which will return the response errors. You can use it to revert Her back to its original behavior (ie. `errors` returning the response errors):
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
class User
|
58
|
+
include Her::Model
|
59
|
+
store_response_errors :errors
|
60
|
+
end
|
61
|
+
|
62
|
+
user = User.create(:email => "foo") # POST /users returns { :errors => ["Email is invalid"] }
|
63
|
+
user.errors # => ["Email is invalid"]
|
64
|
+
```
|
65
|
+
|
66
|
+
## 0.2.4
|
67
|
+
|
68
|
+
Her no longer includes default middleware when making HTTP requests. The user has now to define all the needed middleware. Before:
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
72
|
+
connection.insert(0, FaradayMiddle::OAuth)
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
Now:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
Her::API.setup :url => "https://api.example.com" do |connection|
|
80
|
+
connection.use FaradayMiddle::OAuth
|
81
|
+
connection.use Her::Middleware::FirstLevelParseJSON
|
82
|
+
connection.use Faraday::Request::UrlEncoded
|
83
|
+
connection.use Faraday::Adapter::NetHttp
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
## 0.2
|
88
|
+
|
89
|
+
The default parser middleware has been replaced to treat first-level JSON data as the resource or collection data. Before it expected this:
|
90
|
+
|
91
|
+
```json
|
92
|
+
{ "data": { "id": 1, "name": "Foo" }, "errors": [] }
|
93
|
+
```
|
94
|
+
|
95
|
+
Now it expects this (the `errors` key is not treated as resource data):
|
96
|
+
|
97
|
+
```json
|
98
|
+
{ "id": 1, "name": "Foo", "errors": [] }
|
99
|
+
```
|
100
|
+
|
101
|
+
If you still want to get the old behavior, you can use `Her::Middleware::SecondLevelParseJSON` instead of `Her::Middleware::FirstLevelParseJSON` in your middleware stack.
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "her/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "her"
|
7
|
+
s.version = Her::VERSION
|
8
|
+
s.authors = ["Rémi Prévost"]
|
9
|
+
s.email = ["remi@exomel.com"]
|
10
|
+
s.homepage = "http://her-rb.org"
|
11
|
+
s.license = "MIT"
|
12
|
+
s.summary = "A simple Representational State Transfer-based Hypertext Transfer Protocol-powered Object Relational Mapper. Her?"
|
13
|
+
s.description = "Her is an ORM that maps REST resources and collections to Ruby objects"
|
14
|
+
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency "rake", "~> 10.0"
|
21
|
+
s.add_development_dependency "rspec", "~> 2.13"
|
22
|
+
s.add_development_dependency "rspec-its", "~> 1.0"
|
23
|
+
s.add_development_dependency "fivemat", "~> 1.2"
|
24
|
+
s.add_development_dependency "json", "~> 1.8"
|
25
|
+
s.add_development_dependency "pry"
|
26
|
+
|
27
|
+
s.add_runtime_dependency "activemodel", ">= 3.0.0", "<= 4.3.0"
|
28
|
+
s.add_runtime_dependency "activesupport", ">= 3.0.0", "<= 4.3.0"
|
29
|
+
s.add_runtime_dependency "faraday", ">= 0.8", "< 1.0"
|
30
|
+
s.add_runtime_dependency "multi_json", "~> 1.7"
|
31
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Her
|
2
|
+
# This class is where all HTTP requests are made. Before using Her, you must configure it
|
3
|
+
# so it knows where to make those requests. In Rails, this is usually done in `config/initializers/her.rb`:
|
4
|
+
class API
|
5
|
+
# @private
|
6
|
+
attr_reader :connection, :options
|
7
|
+
|
8
|
+
# Constants
|
9
|
+
FARADAY_OPTIONS = [:request, :proxy, :ssl, :builder, :url, :parallel_manager, :params, :headers, :builder_class].freeze
|
10
|
+
|
11
|
+
# Setup a default API connection. Accepted arguments and options are the same as {API#setup}.
|
12
|
+
def self.setup(opts={}, &block)
|
13
|
+
@default_api = new(opts, &block)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Create a new API object. This is useful to create multiple APIs and use them with the `uses_api` method.
|
17
|
+
# If your application uses only one API, you should use Her::API.setup to configure the default API
|
18
|
+
#
|
19
|
+
# @example Setting up a new API
|
20
|
+
# api = Her::API.new :url => "https://api.example" do |connection|
|
21
|
+
# connection.use Faraday::Request::UrlEncoded
|
22
|
+
# connection.use Her::Middleware::DefaultParseJSON
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# class User
|
26
|
+
# uses_api api
|
27
|
+
# end
|
28
|
+
def initialize(*args, &blk)
|
29
|
+
setup(*args, &blk)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Setup the API connection.
|
33
|
+
#
|
34
|
+
# @param [Hash] opts the Faraday options
|
35
|
+
# @option opts [String] :url The main HTTP API root (eg. `https://api.example.com`)
|
36
|
+
# @option opts [String] :ssl A hash containing [SSL options](https://github.com/lostisland/faraday/wiki/Setting-up-SSL-certificates)
|
37
|
+
#
|
38
|
+
# @return Faraday::Connection
|
39
|
+
#
|
40
|
+
# @example Setting up the default API connection
|
41
|
+
# Her::API.setup :url => "https://api.example"
|
42
|
+
#
|
43
|
+
# @example A custom middleware added to the default list
|
44
|
+
# class MyAuthentication < Faraday::Middleware
|
45
|
+
# def call(env)
|
46
|
+
# env[:request_headers]["X-API-Token"] = "bb2b2dd75413d32c1ac421d39e95b978d1819ff611f68fc2fdd5c8b9c7331192"
|
47
|
+
# @app.call(env)
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
# Her::API.setup :url => "https://api.example.com" do |connection|
|
51
|
+
# connection.use Faraday::Request::UrlEncoded
|
52
|
+
# connection.use Her::Middleware::DefaultParseJSON
|
53
|
+
# connection.use MyAuthentication
|
54
|
+
# connection.use Faraday::Adapter::NetHttp
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# @example A custom parse middleware
|
58
|
+
# class MyCustomParser < Faraday::Response::Middleware
|
59
|
+
# def on_complete(env)
|
60
|
+
# json = JSON.parse(env[:body], :symbolize_names => true)
|
61
|
+
# errors = json.delete(:errors) || {}
|
62
|
+
# metadata = json.delete(:metadata) || []
|
63
|
+
# env[:body] = { :data => json, :errors => errors, :metadata => metadata }
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# Her::API.setup :url => "https://api.example.com" do |connection|
|
67
|
+
# connection.use Faraday::Request::UrlEncoded
|
68
|
+
# connection.use MyCustomParser
|
69
|
+
# connection.use Faraday::Adapter::NetHttp
|
70
|
+
# end
|
71
|
+
def setup(opts={}, &blk)
|
72
|
+
opts[:url] = opts.delete(:base_uri) if opts.include?(:base_uri) # Support legacy :base_uri option
|
73
|
+
@options = opts
|
74
|
+
|
75
|
+
faraday_options = @options.reject { |key, value| !FARADAY_OPTIONS.include?(key.to_sym) }
|
76
|
+
@connection = Faraday.new(faraday_options) do |connection|
|
77
|
+
yield connection if block_given?
|
78
|
+
end
|
79
|
+
self
|
80
|
+
end
|
81
|
+
|
82
|
+
# Define a custom parsing procedure. The procedure is passed the response object and is
|
83
|
+
# expected to return a hash with three keys: a main data Hash, an errors Hash
|
84
|
+
# and a metadata Hash.
|
85
|
+
#
|
86
|
+
# @private
|
87
|
+
def request(params={})
|
88
|
+
method = params.delete(:_method)
|
89
|
+
path = params.delete(:_path)
|
90
|
+
headers = params.delete(:_headers)
|
91
|
+
options = params.delete(:_options) || {}
|
92
|
+
params.delete_if { |key, value| key.to_s =~ /^_/ } # Remove all internal parameters
|
93
|
+
response = @connection.send method do |request|
|
94
|
+
request.headers.merge!(headers) if headers
|
95
|
+
|
96
|
+
timeout = options.delete(:timeout)
|
97
|
+
raise "options not implemented: #{options.keys.join(', ')}" unless options.empty?
|
98
|
+
request.options[:timeout] = timeout if timeout
|
99
|
+
|
100
|
+
if method == :get
|
101
|
+
# For GET requests, treat additional parameters as querystring data
|
102
|
+
request.url path, params
|
103
|
+
else
|
104
|
+
# For POST, PUT and DELETE requests, treat additional parameters as request body
|
105
|
+
request.url path
|
106
|
+
request.body = params
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
{ :parsed_data => response.env[:body], :response => response }
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
# @private
|
115
|
+
def self.default_api(opts={})
|
116
|
+
defined?(@default_api) ? @default_api : nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Her
|
2
|
+
class ErrorCollection
|
3
|
+
attr_reader :metadata, :errors
|
4
|
+
|
5
|
+
# @private
|
6
|
+
def initialize(metadata={}, errors={})
|
7
|
+
@metadata = metadata
|
8
|
+
@errors = errors
|
9
|
+
end
|
10
|
+
|
11
|
+
def method_missing(method_sym, *arguments, &block)
|
12
|
+
raise Her::Errors::ResponseError, "Cannot access collection, Request returned an error"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Her
|
2
|
+
module Errors
|
3
|
+
class PathError < StandardError
|
4
|
+
attr_reader :missing_parameter
|
5
|
+
|
6
|
+
def initialize(message, missing_parameter=nil)
|
7
|
+
super(message)
|
8
|
+
@missing_parameter = missing_parameter
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class AssociationUnknownError < StandardError
|
13
|
+
end
|
14
|
+
|
15
|
+
class ResponseError < StandardError
|
16
|
+
def self.for(status_code)
|
17
|
+
case status_code
|
18
|
+
when 404
|
19
|
+
RecordNotFound
|
20
|
+
when 422
|
21
|
+
RecordInvalid
|
22
|
+
else
|
23
|
+
self
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class ParseError < ResponseError
|
29
|
+
end
|
30
|
+
|
31
|
+
class RemoteServerError < ResponseError
|
32
|
+
end
|
33
|
+
|
34
|
+
class RecordNotFound < ResponseError
|
35
|
+
end
|
36
|
+
|
37
|
+
class RecordInvalid < ResponseError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Her
|
2
|
+
module JsonApi
|
3
|
+
module Model
|
4
|
+
|
5
|
+
def self.included(klass)
|
6
|
+
klass.class_eval do
|
7
|
+
include Her::Model
|
8
|
+
|
9
|
+
[:parse_root_in_json, :include_root_in_json, :root_element, :primary_key].each do |method|
|
10
|
+
define_method method do |*args|
|
11
|
+
raise NoMethodError, "Her::JsonApi::Model does not support the #{method} configuration option"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
method_for :update, :patch
|
16
|
+
|
17
|
+
@type = name.demodulize.tableize
|
18
|
+
|
19
|
+
def self.parse(data)
|
20
|
+
data.fetch(:attributes).merge(data.slice(:id))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.to_params(attributes, changes={})
|
24
|
+
request_data = { type: @type }.tap { |request_body|
|
25
|
+
attrs = attributes.dup.symbolize_keys.tap { |filtered_attributes|
|
26
|
+
if her_api.options[:send_only_modified_attributes]
|
27
|
+
filtered_attributes = changes.symbolize_keys.keys.inject({}) do |hash, attribute|
|
28
|
+
hash[attribute] = filtered_attributes[attribute]
|
29
|
+
hash
|
30
|
+
end
|
31
|
+
end
|
32
|
+
}
|
33
|
+
request_body[:id] = attrs.delete(:id) if attrs[:id]
|
34
|
+
request_body[:attributes] = attrs
|
35
|
+
}
|
36
|
+
{ data: request_data }
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.type(type_name)
|
40
|
+
@type = type_name.to_s
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Her
|
2
|
+
module Middleware
|
3
|
+
# This middleware adds a "Accept: application/json" HTTP header
|
4
|
+
class AcceptJSON < Faraday::Middleware
|
5
|
+
# @private
|
6
|
+
def add_header(headers)
|
7
|
+
headers.merge! "Accept" => "application/json"
|
8
|
+
end
|
9
|
+
|
10
|
+
# @private
|
11
|
+
def call(env)
|
12
|
+
add_header(env[:request_headers])
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Her
|
2
|
+
module Middleware
|
3
|
+
# This middleware treat the received first-level JSON structure as the resource data.
|
4
|
+
class FirstLevelParseJSON < ParseJSON
|
5
|
+
# Parse the response body
|
6
|
+
#
|
7
|
+
# @param [String] body The response body
|
8
|
+
# @return [Mixed] the parsed response
|
9
|
+
# @private
|
10
|
+
def parse(body)
|
11
|
+
json = parse_json(body)
|
12
|
+
errors = json.delete(:errors) || {}
|
13
|
+
metadata = json.delete(:metadata) || {}
|
14
|
+
{
|
15
|
+
:data => json,
|
16
|
+
:errors => errors,
|
17
|
+
:metadata => metadata
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is triggered when the response has been received. It modifies
|
22
|
+
# the value of `env[:body]`.
|
23
|
+
#
|
24
|
+
# @param [Hash] env The response environment
|
25
|
+
# @private
|
26
|
+
def on_complete(env)
|
27
|
+
env[:body] = case env[:status]
|
28
|
+
when 204
|
29
|
+
parse('{}')
|
30
|
+
else
|
31
|
+
parse(env[:body])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Her
|
2
|
+
module Middleware
|
3
|
+
# This middleware expects the resource/collection data to be contained in the `data`
|
4
|
+
# key of the JSON object
|
5
|
+
class JsonApiParser < ParseJSON
|
6
|
+
# Parse the response body
|
7
|
+
#
|
8
|
+
# @param [String] body The response body
|
9
|
+
# @return [Mixed] the parsed response
|
10
|
+
# @private
|
11
|
+
def parse(body)
|
12
|
+
json = parse_json(body)
|
13
|
+
|
14
|
+
{
|
15
|
+
:data => json[:data] || {},
|
16
|
+
:errors => json[:errors] || [],
|
17
|
+
:metadata => json[:meta] || {},
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is triggered when the response has been received. It modifies
|
22
|
+
# the value of `env[:body]`.
|
23
|
+
#
|
24
|
+
# @param [Hash] env The response environment
|
25
|
+
# @private
|
26
|
+
def on_complete(env)
|
27
|
+
env[:body] = case env[:status]
|
28
|
+
when 204
|
29
|
+
parse('{}')
|
30
|
+
else
|
31
|
+
parse(env[:body])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Her
|
2
|
+
module Middleware
|
3
|
+
class ParseJSON < Faraday::Response::Middleware
|
4
|
+
# @private
|
5
|
+
def parse_json(body = nil)
|
6
|
+
body = '{}' if body.blank?
|
7
|
+
message = "Response from the API must behave like a Hash or an Array (last JSON response was #{body.inspect})"
|
8
|
+
|
9
|
+
json = begin
|
10
|
+
MultiJson.load(body, :symbolize_keys => true)
|
11
|
+
rescue MultiJson::LoadError
|
12
|
+
raise Her::Errors::ParseError, message
|
13
|
+
end
|
14
|
+
|
15
|
+
raise Her::Errors::ParseError, message unless json.is_a?(Hash) or json.is_a?(Array)
|
16
|
+
|
17
|
+
json
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Her
|
2
|
+
module Middleware
|
3
|
+
# This middleware expects the resource/collection data to be contained in the `data`
|
4
|
+
# key of the JSON object
|
5
|
+
class SecondLevelParseJSON < ParseJSON
|
6
|
+
# Parse the response body
|
7
|
+
#
|
8
|
+
# @param [String] body The response body
|
9
|
+
# @return [Mixed] the parsed response
|
10
|
+
# @private
|
11
|
+
def parse(body)
|
12
|
+
json = parse_json(body)
|
13
|
+
|
14
|
+
{
|
15
|
+
:data => json[:data],
|
16
|
+
:errors => json[:errors],
|
17
|
+
:metadata => json[:metadata]
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is triggered when the response has been received. It modifies
|
22
|
+
# the value of `env[:body]`.
|
23
|
+
#
|
24
|
+
# @param [Hash] env The response environment
|
25
|
+
# @private
|
26
|
+
def on_complete(env)
|
27
|
+
env[:body] = case env[:status]
|
28
|
+
when 204
|
29
|
+
parse('{}')
|
30
|
+
else
|
31
|
+
parse(env[:body])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "her/middleware/parse_json"
|
2
|
+
require "her/middleware/first_level_parse_json"
|
3
|
+
require "her/middleware/second_level_parse_json"
|
4
|
+
require "her/middleware/accept_json"
|
5
|
+
|
6
|
+
module Her
|
7
|
+
module Middleware
|
8
|
+
DefaultParseJSON = FirstLevelParseJSON
|
9
|
+
|
10
|
+
autoload :JsonApiParser, 'her/middleware/json_api_parser'
|
11
|
+
end
|
12
|
+
end
|