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.
Files changed (113) hide show
  1. checksums.yaml +8 -8
  2. data/README.md +11 -8
  3. data/lib/test_track_rails_client/version.rb +1 -1
  4. data/vendor/gems/fakeable_her/fakeable_her.gemspec +22 -0
  5. data/vendor/gems/fakeable_her/lib/fakeable_her/model.rb +148 -0
  6. data/vendor/gems/fakeable_her/lib/fakeable_her/version.rb +3 -0
  7. data/vendor/gems/fakeable_her/lib/fakeable_her.rb +5 -0
  8. data/vendor/gems/her/CONTRIBUTING.md +26 -0
  9. data/vendor/gems/her/Gemfile +10 -0
  10. data/vendor/gems/her/LICENSE +7 -0
  11. data/vendor/gems/her/README.md +1023 -0
  12. data/vendor/gems/her/Rakefile +11 -0
  13. data/vendor/gems/her/UPGRADE.md +101 -0
  14. data/vendor/gems/her/gemfiles/Gemfile.activemodel-3.2.x +7 -0
  15. data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.0 +7 -0
  16. data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.1 +7 -0
  17. data/vendor/gems/her/gemfiles/Gemfile.activemodel-4.2 +7 -0
  18. data/vendor/gems/her/her.gemspec +31 -0
  19. data/vendor/gems/her/lib/her/api.rb +119 -0
  20. data/vendor/gems/her/lib/her/collection.rb +12 -0
  21. data/vendor/gems/her/lib/her/error_collection.rb +15 -0
  22. data/vendor/gems/her/lib/her/errors.rb +40 -0
  23. data/vendor/gems/her/lib/her/json_api/model.rb +46 -0
  24. data/vendor/gems/her/lib/her/middleware/accept_json.rb +17 -0
  25. data/vendor/gems/her/lib/her/middleware/first_level_parse_json.rb +36 -0
  26. data/vendor/gems/her/lib/her/middleware/json_api_parser.rb +36 -0
  27. data/vendor/gems/her/lib/her/middleware/parse_json.rb +21 -0
  28. data/vendor/gems/her/lib/her/middleware/second_level_parse_json.rb +36 -0
  29. data/vendor/gems/her/lib/her/middleware.rb +12 -0
  30. data/vendor/gems/her/lib/her/model/active_model_overrides.rb +13 -0
  31. data/vendor/gems/her/lib/her/model/associations/association.rb +106 -0
  32. data/vendor/gems/her/lib/her/model/associations/association_proxy.rb +46 -0
  33. data/vendor/gems/her/lib/her/model/associations/belongs_to_association.rb +96 -0
  34. data/vendor/gems/her/lib/her/model/associations/has_many_association.rb +100 -0
  35. data/vendor/gems/her/lib/her/model/associations/has_one_association.rb +79 -0
  36. data/vendor/gems/her/lib/her/model/associations.rb +141 -0
  37. data/vendor/gems/her/lib/her/model/attributes.rb +304 -0
  38. data/vendor/gems/her/lib/her/model/base.rb +33 -0
  39. data/vendor/gems/her/lib/her/model/deprecated_methods.rb +61 -0
  40. data/vendor/gems/her/lib/her/model/http.rb +117 -0
  41. data/vendor/gems/her/lib/her/model/introspection.rb +65 -0
  42. data/vendor/gems/her/lib/her/model/nested_attributes.rb +45 -0
  43. data/vendor/gems/her/lib/her/model/orm.rb +219 -0
  44. data/vendor/gems/her/lib/her/model/parse.rb +215 -0
  45. data/vendor/gems/her/lib/her/model/paths.rb +126 -0
  46. data/vendor/gems/her/lib/her/model/relation.rb +251 -0
  47. data/vendor/gems/her/lib/her/model.rb +81 -0
  48. data/vendor/gems/her/lib/her/version.rb +3 -0
  49. data/vendor/gems/her/lib/her.rb +20 -0
  50. data/vendor/gems/her/spec/api_spec.rb +114 -0
  51. data/vendor/gems/her/spec/collection_spec.rb +26 -0
  52. data/vendor/gems/her/spec/error_collection_spec.rb +33 -0
  53. data/vendor/gems/her/spec/json_api/model_spec.rb +168 -0
  54. data/vendor/gems/her/spec/middleware/accept_json_spec.rb +10 -0
  55. data/vendor/gems/her/spec/middleware/first_level_parse_json_spec.rb +62 -0
  56. data/vendor/gems/her/spec/middleware/json_api_parser_spec.rb +32 -0
  57. data/vendor/gems/her/spec/middleware/second_level_parse_json_spec.rb +35 -0
  58. data/vendor/gems/her/spec/model/associations/association_proxy_spec.rb +31 -0
  59. data/vendor/gems/her/spec/model/associations_spec.rb +504 -0
  60. data/vendor/gems/her/spec/model/attributes_spec.rb +404 -0
  61. data/vendor/gems/her/spec/model/callbacks_spec.rb +145 -0
  62. data/vendor/gems/her/spec/model/dirty_spec.rb +110 -0
  63. data/vendor/gems/her/spec/model/http_spec.rb +165 -0
  64. data/vendor/gems/her/spec/model/introspection_spec.rb +76 -0
  65. data/vendor/gems/her/spec/model/nested_attributes_spec.rb +134 -0
  66. data/vendor/gems/her/spec/model/orm_spec.rb +791 -0
  67. data/vendor/gems/her/spec/model/parse_spec.rb +372 -0
  68. data/vendor/gems/her/spec/model/paths_spec.rb +347 -0
  69. data/vendor/gems/her/spec/model/relation_spec.rb +226 -0
  70. data/vendor/gems/her/spec/model/validations_spec.rb +42 -0
  71. data/vendor/gems/her/spec/model_spec.rb +31 -0
  72. data/vendor/gems/her/spec/spec_helper.rb +27 -0
  73. data/vendor/gems/her/spec/support/extensions/array.rb +5 -0
  74. data/vendor/gems/her/spec/support/extensions/hash.rb +5 -0
  75. data/vendor/gems/her/spec/support/macros/her_macros.rb +17 -0
  76. data/vendor/gems/her/spec/support/macros/model_macros.rb +36 -0
  77. data/vendor/gems/her/spec/support/macros/request_macros.rb +27 -0
  78. data/vendor/gems/publicsuffix-ruby/CHANGELOG.md +236 -0
  79. data/vendor/gems/publicsuffix-ruby/Gemfile +3 -0
  80. data/vendor/gems/publicsuffix-ruby/LICENSE.txt +22 -0
  81. data/vendor/gems/publicsuffix-ruby/README.md +151 -0
  82. data/vendor/gems/publicsuffix-ruby/Rakefile +109 -0
  83. data/vendor/gems/publicsuffix-ruby/lib/definitions.txt +11467 -0
  84. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/domain.rb +387 -0
  85. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/errors.rb +53 -0
  86. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/list.rb +302 -0
  87. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/rule.rb +373 -0
  88. data/vendor/gems/publicsuffix-ruby/lib/public_suffix/version.rb +23 -0
  89. data/vendor/gems/publicsuffix-ruby/lib/public_suffix.rb +131 -0
  90. data/vendor/gems/publicsuffix-ruby/public_suffix.gemspec +39 -0
  91. data/vendor/gems/publicsuffix-ruby/test/acceptance_test.rb +42 -0
  92. data/vendor/gems/publicsuffix-ruby/test/test_helper.rb +6 -0
  93. data/vendor/gems/publicsuffix-ruby/test/unit/domain_test.rb +170 -0
  94. data/vendor/gems/publicsuffix-ruby/test/unit/errors_test.rb +23 -0
  95. data/vendor/gems/publicsuffix-ruby/test/unit/list_test.rb +179 -0
  96. data/vendor/gems/publicsuffix-ruby/test/unit/public_suffix_test.rb +115 -0
  97. data/vendor/gems/publicsuffix-ruby/test/unit/rule_test.rb +307 -0
  98. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/capybara_configuration.rb +98 -0
  99. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/matchers.rb +151 -0
  100. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rspec_configuration.rb +34 -0
  101. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/html_safe.rb +15 -0
  102. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/raw.rb +15 -0
  103. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop/cop/betterment/safe_concat.rb +15 -0
  104. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/rubocop.rb +3 -0
  105. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples/betterment_application_examples.rb +47 -0
  106. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/shared_examples.rb +1 -0
  107. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_configuration.rb +42 -0
  108. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/site_prism_dropdown.rb +17 -0
  109. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/version.rb +3 -0
  110. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers/webmock_configuration.rb +8 -0
  111. data/vendor/gems/ruby_spec_helpers/lib/ruby_spec_helpers.rb +2 -0
  112. data/vendor/gems/ruby_spec_helpers/ruby_spec_helpers.gemspec +25 -0
  113. metadata +110 -1
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ require "rake"
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ task :default => :spec
7
+
8
+ desc "Run all specs"
9
+ RSpec::Core::RakeTask.new(:spec) do |task|
10
+ task.pattern = "spec/**/*_spec.rb"
11
+ end
@@ -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,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem 'activemodel', '~> 3.2.0'
6
+ gem 'activesupport', '~> 3.2.0'
7
+ gem 'faraday', '~> 0.8.9'
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem 'activemodel', '~> 4.0.0'
6
+ gem 'activesupport', '~> 4.0.0'
7
+ gem 'faraday', '~> 0.8.9'
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem 'activemodel', '~> 4.1.0'
6
+ gem 'activesupport', '~> 4.1.0'
7
+ gem 'faraday', '~> 0.8.9'
@@ -0,0 +1,7 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem 'activemodel', '~> 4.2.0'
6
+ gem 'activesupport', '~> 4.2.0'
7
+ gem 'faraday', '~> 0.8.9'
@@ -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,12 @@
1
+ module Her
2
+ class Collection < ::Array
3
+ attr_reader :metadata, :errors
4
+
5
+ # @private
6
+ def initialize(items=[], metadata={}, errors={})
7
+ super(items)
8
+ @metadata = metadata
9
+ @errors = errors
10
+ end
11
+ end
12
+ 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
@@ -0,0 +1,13 @@
1
+ module Her
2
+ module Model
3
+ module ActiveModelOverrides
4
+ extend ActiveSupport::Concern
5
+
6
+ def errors
7
+ errors = super
8
+ errors.messages.merge! @response_errors unless @response_errors.empty?
9
+ errors
10
+ end
11
+ end
12
+ end
13
+ end