her 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop.yml +19 -1279
  3. data/.rubocop_todo.yml +232 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +16 -4
  6. data/README.md +25 -1
  7. data/gemfiles/Gemfile.faraday-1.0 +6 -0
  8. data/her.gemspec +4 -3
  9. data/lib/her/api.rb +8 -7
  10. data/lib/her/collection.rb +2 -1
  11. data/lib/her/errors.rb +3 -1
  12. data/lib/her/json_api/model.rb +8 -12
  13. data/lib/her/middleware.rb +1 -1
  14. data/lib/her/middleware/accept_json.rb +1 -0
  15. data/lib/her/middleware/first_level_parse_json.rb +6 -5
  16. data/lib/her/middleware/json_api_parser.rb +6 -5
  17. data/lib/her/middleware/parse_json.rb +2 -1
  18. data/lib/her/middleware/second_level_parse_json.rb +6 -5
  19. data/lib/her/model/associations.rb +7 -7
  20. data/lib/her/model/associations/association.rb +7 -9
  21. data/lib/her/model/associations/association_proxy.rb +2 -3
  22. data/lib/her/model/associations/belongs_to_association.rb +2 -3
  23. data/lib/her/model/attributes.rb +14 -6
  24. data/lib/her/model/base.rb +2 -2
  25. data/lib/her/model/http.rb +7 -2
  26. data/lib/her/model/introspection.rb +5 -3
  27. data/lib/her/model/nested_attributes.rb +1 -1
  28. data/lib/her/model/orm.rb +27 -9
  29. data/lib/her/model/parse.rb +10 -12
  30. data/lib/her/model/paths.rb +3 -4
  31. data/lib/her/model/relation.rb +5 -4
  32. data/lib/her/version.rb +1 -1
  33. data/spec/api_spec.rb +3 -0
  34. data/spec/middleware/accept_json_spec.rb +1 -0
  35. data/spec/middleware/first_level_parse_json_spec.rb +2 -1
  36. data/spec/middleware/json_api_parser_spec.rb +1 -0
  37. data/spec/middleware/second_level_parse_json_spec.rb +1 -0
  38. data/spec/model/associations/association_proxy_spec.rb +1 -0
  39. data/spec/model/associations_spec.rb +98 -14
  40. data/spec/model/attributes_spec.rb +9 -3
  41. data/spec/model/callbacks_spec.rb +14 -15
  42. data/spec/model/dirty_spec.rb +1 -0
  43. data/spec/model/http_spec.rb +29 -18
  44. data/spec/model/introspection_spec.rb +3 -2
  45. data/spec/model/nested_attributes_spec.rb +1 -0
  46. data/spec/model/orm_spec.rb +39 -16
  47. data/spec/model/parse_spec.rb +24 -0
  48. data/spec/model/paths_spec.rb +1 -0
  49. data/spec/model/relation_spec.rb +3 -2
  50. data/spec/model/validations_spec.rb +1 -0
  51. data/spec/model_spec.rb +1 -0
  52. data/spec/support/extensions/array.rb +1 -0
  53. data/spec/support/extensions/hash.rb +1 -0
  54. metadata +15 -19
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,232 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config`
3
+ # on 2018-05-16 14:33:11 -0300 using RuboCop version 0.54.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Offense count: 2
10
+ # Configuration parameters: Include.
11
+ # Include: **/*.gemfile, **/Gemfile, **/gems.rb
12
+ Bundler/DuplicatedGem:
13
+ Exclude:
14
+ - 'Gemfile'
15
+
16
+ # Offense count: 1
17
+ Lint/EmptyWhen:
18
+ Exclude:
19
+ - 'lib/her/model/parse.rb'
20
+
21
+ # Offense count: 1
22
+ Lint/IneffectiveAccessModifier:
23
+ Exclude:
24
+ - 'lib/her/api.rb'
25
+
26
+ # Offense count: 6
27
+ # Cop supports --auto-correct.
28
+ # Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
29
+ Lint/UnusedMethodArgument:
30
+ Exclude:
31
+ - 'lib/her/api.rb'
32
+ - 'lib/her/model/associations/association.rb'
33
+ - 'lib/her/model/attributes.rb'
34
+ - 'lib/her/model/orm.rb'
35
+ - 'spec/model/attributes_spec.rb'
36
+
37
+ # Offense count: 1
38
+ # Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
39
+ Lint/UselessAccessModifier:
40
+ Exclude:
41
+ - 'lib/her/api.rb'
42
+
43
+ # Offense count: 10
44
+ Metrics/AbcSize:
45
+ Max: 38
46
+
47
+ # Offense count: 91
48
+ # Configuration parameters: CountComments, ExcludedMethods.
49
+ Metrics/BlockLength:
50
+ Max: 694
51
+
52
+ # Offense count: 4
53
+ Metrics/CyclomaticComplexity:
54
+ Max: 12
55
+
56
+ # Offense count: 10
57
+ # Configuration parameters: CountComments.
58
+ Metrics/MethodLength:
59
+ Max: 28
60
+
61
+ # Offense count: 1
62
+ # Configuration parameters: CountComments.
63
+ Metrics/ModuleLength:
64
+ Max: 106
65
+
66
+ # Offense count: 4
67
+ Metrics/PerceivedComplexity:
68
+ Max: 12
69
+
70
+ # Offense count: 4
71
+ Naming/MemoizedInstanceVariableName:
72
+ Exclude:
73
+ - 'lib/her/model/associations.rb'
74
+ - 'lib/her/model/attributes.rb'
75
+ - 'lib/her/model/relation.rb'
76
+
77
+ # Offense count: 7
78
+ # Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros.
79
+ # NamePrefix: is_, has_, have_
80
+ # NamePrefixBlacklist: is_, has_, have_
81
+ # NameWhitelist: is_a?
82
+ # MethodDefinitionMacros: define_method, define_singleton_method
83
+ Naming/PredicateName:
84
+ Exclude:
85
+ - 'spec/**/*'
86
+ - 'lib/her/model/associations.rb'
87
+ - 'lib/her/model/attributes.rb'
88
+ - 'lib/her/model/base.rb'
89
+ - 'lib/her/model/deprecated_methods.rb'
90
+
91
+ # Offense count: 1
92
+ # Cop supports --auto-correct.
93
+ Performance/RegexpMatch:
94
+ Exclude:
95
+ - 'spec/support/macros/model_macros.rb'
96
+
97
+ # Offense count: 23
98
+ Style/Documentation:
99
+ Enabled: false
100
+
101
+ # Offense count: 21
102
+ # Cop supports --auto-correct.
103
+ Style/Encoding:
104
+ Enabled: false
105
+
106
+ # Offense count: 2
107
+ # Cop supports --auto-correct.
108
+ Style/ExpandPathArguments:
109
+ Exclude:
110
+ - 'her.gemspec'
111
+ - 'spec/spec_helper.rb'
112
+
113
+ # Offense count: 59
114
+ # Cop supports --auto-correct.
115
+ # Configuration parameters: EnforcedStyle.
116
+ # SupportedStyles: when_needed, always, never
117
+ Style/FrozenStringLiteralComment:
118
+ Enabled: false
119
+
120
+ # Offense count: 89
121
+ # Cop supports --auto-correct.
122
+ # Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
123
+ # SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
124
+ Style/HashSyntax:
125
+ Enabled: false
126
+
127
+ # Offense count: 6
128
+ # Cop supports --auto-correct.
129
+ Style/IfUnlessModifier:
130
+ Exclude:
131
+ - 'lib/her/json_api/model.rb'
132
+ - 'lib/her/model/associations/association_proxy.rb'
133
+ - 'lib/her/model/nested_attributes.rb'
134
+ - 'lib/her/model/orm.rb'
135
+ - 'lib/her/model/parse.rb'
136
+
137
+ # Offense count: 2
138
+ Style/MethodMissing:
139
+ Exclude:
140
+ - 'lib/her/model/associations/association_proxy.rb'
141
+ - 'lib/her/model/relation.rb'
142
+
143
+ # Offense count: 2
144
+ # Cop supports --auto-correct.
145
+ Style/MutableConstant:
146
+ Exclude:
147
+ - 'lib/her/model/http.rb'
148
+ - 'lib/her/version.rb'
149
+
150
+ # Offense count: 3
151
+ # Cop supports --auto-correct.
152
+ Style/PerlBackrefs:
153
+ Exclude:
154
+ - 'lib/her/model/paths.rb'
155
+
156
+ # Offense count: 1
157
+ # Cop supports --auto-correct.
158
+ # Configuration parameters: EnforcedStyle, AllowInnerSlashes.
159
+ # SupportedStyles: slashes, percent_r, mixed
160
+ Style/RegexpLiteral:
161
+ Exclude:
162
+ - 'lib/her/model/paths.rb'
163
+
164
+ # Offense count: 1
165
+ # Cop supports --auto-correct.
166
+ # Configuration parameters: ConvertCodeThatCanStartToReturnNil, Whitelist.
167
+ # Whitelist: present?, blank?, presence, try
168
+ Style/SafeNavigation:
169
+ Exclude:
170
+ - 'spec/model/orm_spec.rb'
171
+
172
+ # Offense count: 1
173
+ # Cop supports --auto-correct.
174
+ # Configuration parameters: EnforcedStyle.
175
+ # SupportedStyles: use_perl_names, use_english_names
176
+ Style/SpecialGlobalVars:
177
+ Exclude:
178
+ - 'her.gemspec'
179
+
180
+ # Offense count: 1613
181
+ # Cop supports --auto-correct.
182
+ # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
183
+ # SupportedStyles: single_quotes, double_quotes
184
+ Style/StringLiterals:
185
+ Enabled: false
186
+
187
+ # Offense count: 1
188
+ # Cop supports --auto-correct.
189
+ # Configuration parameters: EnforcedStyle.
190
+ # SupportedStyles: single_quotes, double_quotes
191
+ Style/StringLiteralsInInterpolation:
192
+ Exclude:
193
+ - 'lib/her/model/introspection.rb'
194
+
195
+ # Offense count: 1
196
+ # Cop supports --auto-correct.
197
+ # Configuration parameters: IgnoredMethods.
198
+ # IgnoredMethods: respond_to, define_method
199
+ Style/SymbolProc:
200
+ Exclude:
201
+ - 'lib/her/model/parse.rb'
202
+
203
+ # Offense count: 2
204
+ # Cop supports --auto-correct.
205
+ # Configuration parameters: EnforcedStyle, AllowSafeAssignment.
206
+ # SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex
207
+ Style/TernaryParentheses:
208
+ Exclude:
209
+ - 'lib/her/model/http.rb'
210
+ - 'lib/her/model/orm.rb'
211
+
212
+ # Offense count: 1
213
+ # Cop supports --auto-correct.
214
+ # Configuration parameters: EnforcedStyleForMultiline.
215
+ # SupportedStylesForMultiline: comma, consistent_comma, no_comma
216
+ Style/TrailingCommaInHashLiteral:
217
+ Exclude:
218
+ - 'lib/her/middleware/json_api_parser.rb'
219
+
220
+ # Offense count: 6
221
+ # Cop supports --auto-correct.
222
+ # Configuration parameters: EnforcedStyle, MinSize, WordRegex.
223
+ # SupportedStyles: percent, brackets
224
+ Style/WordArray:
225
+ Exclude:
226
+ - 'spec/model/orm_spec.rb'
227
+
228
+ # Offense count: 409
229
+ # Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
230
+ # URISchemes: http, https
231
+ Metrics/LineLength:
232
+ Max: 377
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.4
data/.travis.yml CHANGED
@@ -6,15 +6,18 @@ rvm:
6
6
  - 1.9.3
7
7
  - 2.0.0
8
8
  - 2.1.6
9
- - 2.2.8
10
- - 2.3.5
11
- - 2.4.2
9
+ - 2.2.10
10
+ - 2.3.7
11
+ - 2.4.3
12
+ - 2.5.1
13
+ - 2.6.6
12
14
 
13
15
  gemfile:
14
16
  - gemfiles/Gemfile.activemodel-4.2
15
17
  - gemfiles/Gemfile.activemodel-5.0
16
18
  - gemfiles/Gemfile.activemodel-5.1
17
19
  - gemfiles/Gemfile.activemodel-5.2
20
+ - gemfiles/Gemfile.faraday-1.0
18
21
 
19
22
  matrix:
20
23
  exclude:
@@ -36,8 +39,17 @@ matrix:
36
39
  rvm: 2.0.0
37
40
  - gemfile: gemfiles/Gemfile.activemodel-5.2
38
41
  rvm: 2.1.6
42
+ - gemfile: gemfiles/Gemfile.faraday-1.0
43
+ rvm: 1.9.3
44
+ - gemfile: gemfiles/Gemfile.faraday-1.0
45
+ rvm: 2.0.0
46
+ - gemfile: gemfiles/Gemfile.faraday-1.0
47
+ rvm: 2.1.6
48
+ - gemfile: gemfiles/Gemfile.faraday-1.0
49
+ rvm: 2.2.10
39
50
 
40
51
  before_install:
41
- - gem install bundler
52
+ - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
53
+ - gem install bundler -v '< 2'
42
54
 
43
55
  script: "echo 'COME ON!' && bundle exec rake spec"
data/README.md CHANGED
@@ -91,6 +91,10 @@ user.fullname = "Lindsay Fünke" # OR user.assign_attributes(fullname: "Lindsay
91
91
  user.save # returns false if it fails, errors in user.response_errors array
92
92
  # PUT "/users/1" with `fullname=Lindsay+Fünke`
93
93
 
94
+ user.update_attributes(fullname: "Maeby Fünke")
95
+ # PUT "/users/1" with `fullname=Maeby+Fünke`
96
+
97
+ # => PUT /users/1 { "id": 1, "name": "new new name" }
94
98
  # Update a resource without fetching it
95
99
  User.save_existing(1, fullname: "Lindsay Fünke")
96
100
  # PUT "/users/1" with `fullname=Lindsay+Fünke`
@@ -452,6 +456,22 @@ Her expects all `User` resources to have an `:organization_id` (or `:_organizati
452
456
  Her::Errors::PathError: Missing :_organization_id parameter to build the request path. Path is `organizations/:organization_id/users`. Parameters are `{ … }`.
453
457
  ```
454
458
 
459
+ #### Associations with custom attributes
460
+
461
+ Associations can also be made using custom attributes:
462
+
463
+ ```ruby
464
+ class User
465
+ include Her::Model
466
+ belongs_to :owns, class_name: "Organization"
467
+ end
468
+
469
+ class Organization
470
+ include Her::Model
471
+ has_many :owners, class_name: "User"
472
+ end
473
+ ```
474
+
455
475
  ### Validations
456
476
 
457
477
  Her includes `ActiveModel::Validations` so you can declare validations the same way you do in Rails.
@@ -655,7 +675,7 @@ class User
655
675
  include Her::Model
656
676
 
657
677
  custom_get :popular, :unpopular
658
- custom_post :from_default
678
+ custom_post :from_default, :activate
659
679
  end
660
680
 
661
681
  User.popular
@@ -669,6 +689,10 @@ User.unpopular
669
689
  User.from_default(name: "Maeby Fünke")
670
690
  # POST "/users/from_default" with `name=Maeby+Fünke`
671
691
  # => #<User id=5 name="Maeby Fünke">
692
+
693
+ User.activate(id: 6)
694
+ # POST "/users/6/activate"
695
+ # => #<User id=6>
672
696
  ```
673
697
 
674
698
  You can also use `get`, `post`, `put` or `delete` (which maps the returned data to either a collection or a resource).
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec :path => "../"
4
+
5
+ gem 'activemodel', '~> 4.2.1'
6
+ gem 'faraday', '~> 1.0'
data/her.gemspec CHANGED
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  $:.push File.expand_path("../lib", __FILE__)
3
4
  require "her/version"
4
5
 
@@ -14,14 +15,14 @@ Gem::Specification.new do |s|
14
15
 
15
16
  s.files = `git ls-files`.split("\n")
16
17
  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.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
18
19
  s.require_paths = ["lib"]
19
20
 
21
+ s.add_development_dependency "json", "~> 1.8"
20
22
  s.add_development_dependency "rake", "~> 10.0"
21
23
  s.add_development_dependency "rspec", "~> 3.5"
22
- s.add_development_dependency "json", "~> 1.8"
23
24
 
24
25
  s.add_runtime_dependency "activemodel", ">= 4.2.1"
25
- s.add_runtime_dependency "faraday", ">= 0.8", "< 1.0"
26
+ s.add_runtime_dependency "faraday", ">= 0.8"
26
27
  s.add_runtime_dependency "multi_json", "~> 1.7"
27
28
  end
data/lib/her/api.rb CHANGED
@@ -2,6 +2,7 @@ module Her
2
2
  # This class is where all HTTP requests are made. Before using Her, you must configure it
3
3
  # so it knows where to make those requests. In Rails, this is usually done in `config/initializers/her.rb`:
4
4
  class API
5
+
5
6
  # @private
6
7
  attr_reader :connection, :options
7
8
 
@@ -9,7 +10,7 @@ module Her
9
10
  FARADAY_OPTIONS = [:request, :proxy, :ssl, :builder, :url, :parallel_manager, :params, :headers, :builder_class].freeze
10
11
 
11
12
  # Setup a default API connection. Accepted arguments and options are the same as {API#setup}.
12
- def self.setup(opts={}, &block)
13
+ def self.setup(opts = {}, &block)
13
14
  @default_api = new(opts, &block)
14
15
  end
15
16
 
@@ -68,11 +69,11 @@ module Her
68
69
  # connection.use MyCustomParser
69
70
  # connection.use Faraday::Adapter::NetHttp
70
71
  # end
71
- def setup(opts={}, &blk)
72
+ def setup(opts = {}, &blk)
72
73
  opts[:url] = opts.delete(:base_uri) if opts.include?(:base_uri) # Support legacy :base_uri option
73
74
  @options = opts
74
75
 
75
- faraday_options = @options.reject { |key, value| !FARADAY_OPTIONS.include?(key.to_sym) }
76
+ faraday_options = @options.select { |key, _| FARADAY_OPTIONS.include?(key.to_sym) }
76
77
  @connection = Faraday.new(faraday_options) do |connection|
77
78
  yield connection if block_given?
78
79
  end
@@ -84,11 +85,11 @@ module Her
84
85
  # and a metadata Hash.
85
86
  #
86
87
  # @private
87
- def request(opts={})
88
+ def request(opts = {})
88
89
  method = opts.delete(:_method)
89
90
  path = opts.delete(:_path)
90
91
  headers = opts.delete(:_headers)
91
- opts.delete_if { |key, value| key.to_s =~ /^_/ } # Remove all internal parameters
92
+ opts.delete_if { |key, _| key.to_s =~ /^_/ } # Remove all internal parameters
92
93
  if method == :options
93
94
  # Faraday doesn't support the OPTIONS verb because of a name collision with an internal options method
94
95
  # so we need to call run_request directly.
@@ -108,12 +109,12 @@ module Her
108
109
  end
109
110
  end
110
111
  { :parsed_data => response.env[:body], :response => response }
111
-
112
112
  end
113
113
 
114
114
  private
115
+
115
116
  # @private
116
- def self.default_api(opts={})
117
+ def self.default_api(opts = {})
117
118
  defined?(@default_api) ? @default_api : nil
118
119
  end
119
120
  end
@@ -1,9 +1,10 @@
1
1
  module Her
2
2
  class Collection < ::Array
3
+
3
4
  attr_reader :metadata, :errors
4
5
 
5
6
  # @private
6
- def initialize(items=[], metadata={}, errors={})
7
+ def initialize(items = [], metadata = {}, errors = {})
7
8
  super(items)
8
9
  @metadata = metadata
9
10
  @errors = errors
data/lib/her/errors.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  module Her
2
2
  module Errors
3
3
  class PathError < StandardError
4
+
4
5
  attr_reader :missing_parameter
5
6
 
6
- def initialize(message, missing_parameter=nil)
7
+ def initialize(message, missing_parameter = nil)
7
8
  super(message)
8
9
  @missing_parameter = missing_parameter
9
10
  end
@@ -16,6 +17,7 @@ module Her
16
17
  end
17
18
 
18
19
  class ResourceInvalid < StandardError
20
+
19
21
  attr_reader :resource
20
22
  def initialize(resource)
21
23
  @resource = resource