client-api-builder 0.5.6 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 212fbedc035c5b2b1b406bd024a10b1739839d540a4be74ef2b67d57ed3a29d8
4
- data.tar.gz: 18160a35e27ff5432a35a266b7062adda945de69f7c5e7eb6494a25cfbb66c5d
3
+ metadata.gz: ae35befd024cba590ae2f644877243c536612ef9ce0e66c6c7c69f2481a7fc20
4
+ data.tar.gz: cd843e5f96ed9a63f9fb4012ab94b7ebe7b8bd443fa2cec35fe04e1bf50e0806
5
5
  SHA512:
6
- metadata.gz: fec92f548db39eec3123b5ea613f6d390af534def8c60fb1522323dd2d2c578cb6a657b896896aad05d36f7bcb9e93dcf60fc282f1c8cefa3c477113d675d106
7
- data.tar.gz: ec306c4f5d78b85da0bbf5ea97c19a1e012053af75447d40600e2c358635a681579dbb933b44c40d46e4a0159a1ffe72f427270fa2833eeb34f9ad16db93575f
6
+ metadata.gz: a97833f34c6dde60bc8edbe9d38180e6f2904884ceb5b85a38e43358856e6e9c95f57e06f4356c0a10fe50d33801513e89132b452482bd689abf610a9ac53894
7
+ data.tar.gz: 9686a7f14ed8144f3e310cddf9abdf0681bfd237149397adba9d1376ca5d47a106530e099e165d22264bd7178b663e026a9e0658a2e95ef6a9b1fb1c3beb874e
@@ -0,0 +1,53 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ pull_request:
7
+ branches: [master]
8
+
9
+ jobs:
10
+ lint:
11
+ name: RuboCop
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '3.4'
20
+ bundler-cache: true
21
+
22
+ - name: Run RuboCop
23
+ run: bundle exec rubocop --format github
24
+
25
+ test:
26
+ name: Tests (Ruby ${{ matrix.ruby }})
27
+ runs-on: ubuntu-latest
28
+ strategy:
29
+ fail-fast: false
30
+ matrix:
31
+ ruby: ['3.2', '3.3', '3.4']
32
+
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+
36
+ - name: Set up Ruby ${{ matrix.ruby }}
37
+ uses: ruby/setup-ruby@v1
38
+ with:
39
+ ruby-version: ${{ matrix.ruby }}
40
+ bundler-cache: true
41
+
42
+ - name: Run tests
43
+ run: bundle exec rspec
44
+
45
+ - name: Upload coverage to Codecov
46
+ if: matrix.ruby == '3.4'
47
+ uses: codecov/codecov-action@v4
48
+ with:
49
+ files: coverage/coverage.xml
50
+ fail_ci_if_error: false
51
+ verbose: true
52
+ env:
53
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
data/.rubocop.yml ADDED
@@ -0,0 +1,79 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.2
3
+ NewCops: enable
4
+ SuggestExtensions: false
5
+ Exclude:
6
+ - 'bin/**/*'
7
+ - 'vendor/**/*'
8
+ - 'coverage/**/*'
9
+
10
+ # Relaxed metrics for existing codebase
11
+ Metrics/MethodLength:
12
+ Max: 100
13
+
14
+ Metrics/AbcSize:
15
+ Max: 80
16
+
17
+ Metrics/ClassLength:
18
+ Max: 200
19
+
20
+ Metrics/ModuleLength:
21
+ Max: 320
22
+
23
+ Metrics/CyclomaticComplexity:
24
+ Max: 30
25
+
26
+ Metrics/PerceivedComplexity:
27
+ Max: 30
28
+
29
+ Metrics/BlockLength:
30
+ Exclude:
31
+ - 'spec/**/*'
32
+ - '*.gemspec'
33
+
34
+ Metrics/ParameterLists:
35
+ Max: 7
36
+
37
+ # Style preferences
38
+ Style/Documentation:
39
+ Enabled: false
40
+
41
+ Style/FrozenStringLiteralComment:
42
+ EnforcedStyle: always
43
+
44
+ Layout/LineLength:
45
+ Max: 170
46
+ Exclude:
47
+ - 'spec/**/*'
48
+
49
+ # File naming - allow hyphenated gem name
50
+ Naming/FileName:
51
+ Exclude:
52
+ - 'lib/client-api-builder.rb'
53
+
54
+ # Allow short parameter names for unused exception variables
55
+ Naming/MethodParameterName:
56
+ AllowedNames:
57
+ - e
58
+ - _e
59
+ - io
60
+
61
+ # Gemspec settings
62
+ Gemspec/RequiredRubyVersion:
63
+ Enabled: false
64
+
65
+ # Style relaxations for existing code patterns
66
+ Style/OptionalBooleanParameter:
67
+ Enabled: false
68
+
69
+ Style/StringConcatenation:
70
+ Enabled: false
71
+
72
+ Style/FormatStringToken:
73
+ Enabled: false
74
+
75
+ # Note: Previously had exclusions for Style/ClassVars, Style/PerlBackrefs, and
76
+ # Lint/RescueException in router.rb - these have been fixed:
77
+ # - ClassVars: Changed to thread-local storage
78
+ # - PerlBackrefs: Changed to Regexp.last_match
79
+ # - RescueException: Changed to StandardError
data/ARCHITECTURE.md CHANGED
@@ -6,143 +6,218 @@ This document describes the internal architecture and design of the Client API B
6
6
 
7
7
  Client API Builder is a Ruby gem that provides a declarative way to create API clients. It uses a modular architecture with several key components working together to provide a flexible and extensible API client framework.
8
8
 
9
+ ## File Structure
10
+
11
+ ```
12
+ lib/
13
+ ├── client-api-builder.rb # Main entry point, autoloads, error classes
14
+ └── client_api_builder/
15
+ ├── router.rb # Core Router module with route DSL
16
+ ├── nested_router.rb # NestedRouter class for hierarchical APIs
17
+ ├── section.rb # Section module for creating nested routers
18
+ ├── net_http_request.rb # Net::HTTP request execution and streaming
19
+ ├── query_params.rb # Custom query parameter builder
20
+ ├── active_support_notifications.rb # ActiveSupport instrumentation
21
+ └── active_support_log_subscriber.rb # ActiveSupport logging
22
+ ```
23
+
9
24
  ## Core Components
10
25
 
11
26
  ### 1. Router Module (`ClientApiBuilder::Router`)
12
27
 
13
- The `Router` module is the core component that provides the main functionality for defining and executing API requests. It includes:
28
+ The `Router` module is the core component that provides the main functionality for defining and executing API requests.
29
+
30
+ **Class Methods** (defined in `ClassMethods`):
31
+ - `base_url`: Sets the base URL for all requests
32
+ - `header`: Adds headers to requests (supports values, symbols, or procs)
33
+ - `route`: Defines API endpoints with dynamic method generation
34
+ - `body_builder`: Configures request body formatting (`:to_json`, `:to_query`, `:query_params`, or custom)
35
+ - `query_builder`: Configures query parameter formatting
36
+ - `query_param`: Adds query parameters to all requests
37
+ - `connection_option`: Sets Net::HTTP connection options
38
+ - `configure_retries`: Sets retry behavior (max_retries, sleep time)
39
+ - `namespace`: Groups routes under a common path prefix
40
+
41
+ **Instance Methods**:
42
+ - `build_headers`: Constructs request headers, evaluating procs/symbols
43
+ - `build_connection_options`: Merges default and request-specific options
44
+ - `build_query`: Formats query parameters using configured builder
45
+ - `build_body`: Formats request body using configured builder
46
+ - `build_uri`: Constructs full URI with base_url, path, and query
47
+ - `handle_response`: Processes API responses, parses JSON by default
48
+ - `request_wrapper`: Manages request execution with retry and instrumentation
49
+ - `root_router`: Returns self (overridden in NestedRouter)
50
+
51
+ **Instance Attributes** (via `attr_reader`):
52
+ - `response`: The last Net::HTTP response object
53
+ - `request_options`: Hash of method, uri, body, headers, connection_options
54
+ - `total_request_time`: Duration of last request in seconds
55
+ - `request_attempts`: Number of attempts for last request
56
+
57
+ ### 2. Route Code Generation
58
+
59
+ The `route` class method dynamically generates two methods per endpoint using `generate_route_code`:
60
+
61
+ ```ruby
62
+ route :get_user, '/users/:id', expected_response_code: 200
63
+ ```
64
+
65
+ Generates:
66
+ - `get_user_raw_response(id:, **options, &block)` - Makes HTTP request, sets `@response` and `@request_options`
67
+ - `get_user(id:, **options, &block)` - Wraps raw_response with retry logic, response code validation, and response handling
14
68
 
15
- - **Class Methods**: Configuration methods for setting up the API client
16
- - `base_url`: Sets the base URL for all requests
17
- - `header`: Adds headers to requests
18
- - `route`: Defines API endpoints
19
- - `body_builder`: Configures how request bodies are formatted
20
- - `query_builder`: Configures how query parameters are formatted
21
- - `configure_retries`: Sets retry behavior for failed requests
69
+ **Path Parameters**: Extracted from `:param` or `{param}` syntax in path
70
+ **Body/Query Parameters**: Extracted from `body:` and `query:` options using symbol values
22
71
 
23
- - **Instance Methods**: Methods for executing requests and handling responses
24
- - `build_headers`: Constructs request headers
25
- - `build_connection_options`: Sets up connection options
26
- - `build_query`: Formats query parameters
27
- - `build_body`: Formats request body
28
- - `handle_response`: Processes API responses
29
- - `request_wrapper`: Manages request execution and retries
72
+ ### 3. HTTP Method Auto-Detection
30
73
 
31
- ### 2. Nested Router (`ClientApiBuilder::NestedRouter`)
74
+ When `method:` is not specified in route options, `auto_detect_http_method` infers it from the method name:
32
75
 
33
- The `NestedRouter` class enables hierarchical API client organization by allowing routes to be grouped under namespaces. It:
76
+ | Prefix Pattern | HTTP Method |
77
+ |---------------|-------------|
78
+ | `post`, `create`, `add`, `insert` | POST |
79
+ | `put`, `update`, `modify`, `change` | PUT |
80
+ | `patch` | PATCH |
81
+ | `delete`, `remove` | DELETE |
82
+ | (default) | GET |
34
83
 
35
- - Inherits from the base Router functionality
36
- - Maintains a reference to its root router
37
- - Allows for nested route definitions
38
- - Shares configuration with its parent router
84
+ ### 4. Nested Router (`ClientApiBuilder::NestedRouter`)
39
85
 
40
- ### 3. Section Module (`ClientApiBuilder::Section`)
86
+ Enables hierarchical API client organization:
41
87
 
42
- The `Section` module provides the mechanism for creating nested routers. It:
88
+ ```ruby
89
+ section :users do
90
+ route :list, '/'
91
+ route :get, '/:id'
92
+ end
93
+ # Usage: client.users.get(id: 123)
94
+ ```
95
+
96
+ Key behaviors:
97
+ - Includes `ClientApiBuilder::Router` module
98
+ - Stores `root_router` reference to access shared state
99
+ - Stores `nested_router_options` passed from section definition
100
+ - Overrides `base_url` to fall back to root_router's base_url
101
+ - Delegates `handle_response` to root_router
102
+ - Overrides `get_instance_method` to access root_router's instance variables in paths
43
103
 
44
- - Defines the `section` class method for creating nested route groups
45
- - Dynamically generates methods for accessing nested routers
46
- - Handles the creation of nested router classes
104
+ ### 5. Section Module (`ClientApiBuilder::Section`)
47
105
 
48
- ### 4. Request Handling
106
+ Creates nested routers dynamically using `InheritanceHelper::ClassBuilder::Utils.create_class`:
49
107
 
50
- The request handling system is built on top of Ruby's `Net::HTTP` and includes:
108
+ ```ruby
109
+ def section(name, nested_router_options={}, &block)
110
+ # Creates: MyClient::UsersNestedRouter < ClientApiBuilder::NestedRouter
111
+ # Defines: MyClient.users_router (class method)
112
+ # Defines: MyClient#users (instance method, memoized)
113
+ end
114
+ ```
51
115
 
52
- - **Request Building**: Constructs HTTP requests with proper headers, body, and query parameters
53
- - **Response Processing**: Handles different response formats and status codes
54
- - **Error Handling**: Provides custom error classes for API-specific errors
55
- - **Retry Mechanism**: Implements configurable retry logic for failed requests
116
+ ### 6. NetHTTP::Request Module
56
117
 
57
- ### 5. ActiveSupport Integration
118
+ Provides HTTP request execution using Net::HTTP:
58
119
 
59
- The gem integrates with ActiveSupport for:
120
+ **Methods**:
121
+ - `request(method:, uri:, body:, headers:, connection_options:)` - Standard request with optional block
122
+ - `stream(...)` - Streams response body in chunks via `read_body`
123
+ - `stream_to_io(..., io:)` - Writes streamed chunks to an IO object
124
+ - `stream_to_file(..., file:)` - Opens file and streams to it
60
125
 
61
- - **Logging**: Provides request/response logging
62
- - **Notifications**: Implements instrumentation for request timing and monitoring
63
- - **Query Parameter Building**: Uses ActiveSupport's parameter formatting when available
126
+ **Supported HTTP Methods** (via `METHOD_TO_NET_HTTP_CLASS`):
127
+ `copy`, `delete`, `get`, `head`, `lock`, `mkcol`, `move`, `options`, `patch`, `post`, `propfind`, `proppatch`, `put`, `trace`, `unlock`
64
128
 
65
- ## Design Patterns
129
+ ### 7. QueryParams Class
66
130
 
67
- ### 1. Module Inclusion Pattern
131
+ Standalone query parameter builder (used when ActiveSupport unavailable):
68
132
 
69
- The gem uses Ruby's module inclusion pattern extensively:
133
+ - Handles nested hashes with bracket notation: `user[name]=John`
134
+ - Handles arrays: `ids[]=1&ids[]=2`
135
+ - Configurable separators: `name_value_separator` (default `=`), `param_separator` (default `&`)
136
+ - Supports custom escape proc
137
+
138
+ ### 8. ActiveSupport Integration
139
+
140
+ **ActiveSupportNotifications** (conditionally included when ActiveSupport defined):
141
+ - Overrides `instrument_request` to use `ActiveSupport::Notifications.instrument`
142
+ - Event name: `client_api_builder.request`
143
+ - Payload includes `client: self`
144
+
145
+ **ActiveSupportLogSubscriber**:
146
+ - Subscribes to `client_api_builder.request` events for logging
147
+
148
+ ## Design Patterns
149
+
150
+ ### Module Inclusion Pattern
70
151
 
71
152
  ```ruby
72
153
  module ClientApiBuilder
73
154
  module Router
74
155
  def self.included(base)
156
+ base.extend InheritanceHelper::Methods
75
157
  base.extend ClassMethods
76
- base.include InstanceMethods
158
+ base.include ::ClientApiBuilder::Section
159
+ base.include ::ClientApiBuilder::NetHTTP::Request
160
+ base.include(::ClientApiBuilder::ActiveSupportNotifications) if defined?(ActiveSupport)
161
+ base.send(:attr_reader, :response, :request_options, :total_request_time, :request_attempts)
77
162
  end
78
163
  end
79
164
  end
80
165
  ```
81
166
 
82
- This pattern allows for clean separation of class and instance methods while maintaining a single namespace.
83
-
84
- ### 2. Builder Pattern
85
-
86
- The request building process follows the builder pattern:
167
+ ### Builder Pattern
87
168
 
169
+ Request components built separately then combined:
88
170
  ```ruby
89
- def build_headers(options)
90
- headers = {}
91
- # ... build headers
92
- headers
93
- end
171
+ __uri__ = build_uri(__path__, __query__, __options__)
172
+ __body__ = build_body(__body__, __options__)
173
+ __headers__ = build_headers(__options__)
174
+ __connection_options__ = build_connection_options(__options__)
94
175
  ```
95
176
 
96
- Each component (headers, body, query) is built separately and then combined into the final request.
97
-
98
- ### 3. Decorator Pattern
99
-
100
- The nested router implementation uses a decorator-like pattern:
177
+ ### Configuration Inheritance
101
178
 
179
+ Uses `inheritance-helper` gem's `add_value_to_class_method` for configuration that properly inherits to subclasses:
102
180
  ```ruby
103
- class NestedRouter
104
- include ::ClientApiBuilder::Router
105
- attr_reader :root_router
106
- # ... adds additional functionality while delegating to root_router
181
+ def base_url(url = nil)
182
+ return default_options[:base_url] unless url
183
+ add_value_to_class_method(:default_options, base_url: url)
107
184
  end
108
185
  ```
109
186
 
110
- ## Configuration Management
111
-
112
- The gem uses a hierarchical configuration system:
187
+ ## Configuration Hierarchy
113
188
 
114
- 1. **Default Options**: Defined in `Router.default_options`
115
- 2. **Class-level Configuration**: Set through class methods
116
- 3. **Instance-level Configuration**: Can override class-level settings
117
- 4. **Request-level Configuration**: Specific to individual requests
189
+ 1. **Default Options**: `Router.default_options` returns frozen hash with defaults
190
+ 2. **Class-level Configuration**: Set through DSL methods, stored via `add_value_to_class_method`
191
+ 3. **Instance-level**: Access class config, can override in method calls
192
+ 4. **Request-level**: `**__options__` parameter on generated methods
118
193
 
119
194
  ## Error Handling
120
195
 
121
- The error handling system includes:
122
-
123
196
  - `ClientApiBuilder::Error`: Base error class
124
- - `ClientApiBuilder::UnexpectedResponse`: For handling unexpected API responses
125
- - Custom error handling through response procs
197
+ - `ClientApiBuilder::UnexpectedResponse`: Raised when response code doesn't match expected codes
198
+ - Stores `response` for inspection
199
+ - Response procs: Per-route custom response handling stored in `default_options[:response_procs]`
200
+ - Retry on exception: `retry_request?` method (always returns true by default, override to customize)
126
201
 
127
- ## Extensibility
202
+ ## Streaming Support
128
203
 
129
- The architecture is designed to be extensible through:
204
+ Routes can specify streaming behavior:
130
205
 
131
- 1. **Custom Body Builders**: Implement custom body formatting
132
- 2. **Custom Query Builders**: Implement custom query parameter formatting
133
- 3. **Response Processors**: Add custom response handling
134
- 4. **Nested Routers**: Create custom nested router implementations
206
+ ```ruby
207
+ route :download, '/file', stream: :file # stream_to_file, requires file: argument
208
+ route :stream, '/events', stream: :io # stream_to_io, requires io: argument
209
+ route :process, '/data', stream: :block # stream with block for each chunk
210
+ route :download, '/file', stream: true # alias for :file
211
+ ```
135
212
 
136
213
  ## Dependencies
137
214
 
138
- - `inheritance-helper`: For class inheritance and method management
139
- - `json`: For JSON parsing and serialization
140
- - `net/http`: For HTTP request handling
141
- - `active_support` (optional): For additional functionality when available
215
+ - `inheritance-helper`: Class inheritance and configuration management
216
+ - `json`: JSON parsing and serialization (stdlib)
217
+ - `net/http`: HTTP request handling (stdlib)
218
+ - `cgi`: URL encoding in QueryParams (stdlib)
219
+ - `active_support` (optional): Enhanced query building and instrumentation
142
220
 
143
- ## Performance Considerations
221
+ ## Thread Safety
144
222
 
145
- 1. **Request Caching**: No built-in request caching
146
- 2. **Connection Pooling**: Uses standard Net::HTTP connection handling
147
- 3. **Memory Usage**: Minimal object creation during request processing
148
- 4. **Thread Safety**: No explicit thread safety mechanisms
223
+ The library is not thread-safe. Each client instance maintains state (`@response`, `@request_options`, etc.) that would cause race conditions if shared across threads. Create separate client instances per thread.
data/CLAUDE.md ADDED
@@ -0,0 +1,92 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ Client API Builder is a Ruby gem for creating API clients through declarative configuration. It uses Ruby's module inclusion pattern with `ClientApiBuilder::Router` as the core component.
8
+
9
+ ## Common Commands
10
+
11
+ ```bash
12
+ # Install dependencies
13
+ bundle install
14
+
15
+ # Run all tests
16
+ bundle exec rspec
17
+
18
+ # Run a single test file
19
+ bundle exec rspec spec/client_api_builder/router_spec.rb
20
+
21
+ # Run a specific test by line number
22
+ bundle exec rspec spec/client_api_builder/router_spec.rb:42
23
+
24
+ # Run linter
25
+ bundle exec rubocop
26
+
27
+ # Build the gem
28
+ gem build client-api-builder.gemspec
29
+ ```
30
+
31
+ ## Architecture
32
+
33
+ ### Core Components
34
+
35
+ - **Router** (`lib/client_api_builder/router.rb`): Main module providing `route`, `base_url`, `header`, `body_builder`, `query_builder`, and `configure_retries` class methods. Uses `InheritanceHelper::Methods` for configuration inheritance.
36
+
37
+ - **NestedRouter** (`lib/client_api_builder/nested_router.rb`): Enables hierarchical API organization. Maintains reference to `root_router` and shares configuration with parent.
38
+
39
+ - **Section** (`lib/client_api_builder/section.rb`): Provides `section` class method for creating nested route groups via dynamically generated classes.
40
+
41
+ - **NetHTTP::Request** (`lib/client_api_builder/net_http_request.rb`): HTTP request execution using `Net::HTTP`. Handles standard requests and streaming (`:file`, `:io`, `:block` modes).
42
+
43
+ - **QueryParams** (`lib/client_api_builder/query_params.rb`): Custom query parameter builder used when ActiveSupport's `to_query` is unavailable.
44
+
45
+ - **ActiveSupportNotifications/LogSubscriber**: Optional integration for logging and instrumentation when ActiveSupport is present.
46
+
47
+ ### Route Code Generation
48
+
49
+ The `route` class method in Router uses `generate_route_code` to dynamically create two methods per route:
50
+ 1. `method_name_raw_response` - Makes the HTTP request
51
+ 2. `method_name` - Wraps the request with retry logic and response handling
52
+
53
+ ### HTTP Method Auto-Detection
54
+
55
+ Methods are auto-detected from route names: `post/create/add/insert` → POST, `put/update/modify/change` → PUT, `patch` → PATCH, `delete/remove` → DELETE, others → GET.
56
+
57
+ ### Configuration Hierarchy
58
+
59
+ 1. `default_options` class method (base defaults)
60
+ 2. Class-level configuration via DSL methods
61
+ 3. Instance-level overrides
62
+ 4. Request-level options (`**__options__`)
63
+
64
+ ## Key Patterns
65
+
66
+ - Module inclusion with `self.included(base)` extending ClassMethods and including InstanceMethods
67
+ - `add_value_to_class_method` from `inheritance-helper` for configuration inheritance
68
+ - Response procs stored per method name for custom response handling
69
+ - `root_router` method for accessing the top-level router from nested routers
70
+
71
+ ## Dependencies
72
+
73
+ - `inheritance-helper` (runtime): Class inheritance and method management
74
+ - `webmock` (test): HTTP request stubbing
75
+ - `activesupport` (optional): Enhanced query param building and instrumentation
76
+
77
+ ## Code Commits
78
+
79
+ Format using angular formatting:
80
+ ```
81
+ <type>(<scope>): <short summary>
82
+ ```
83
+ - **type**: build|ci|docs|feat|fix|perf|refactor|test
84
+ - **scope**: The feature or component of the service we're working on
85
+ - **summary**: Summary in present tense. Not capitalized. No period at the end.
86
+
87
+ ## Documentation Maintenance
88
+
89
+ When modifying the codebase, keep documentation in sync:
90
+ - **ARCHITECTURE.md** - Update when adding/removing classes, changing component relationships, or altering data flow patterns
91
+ - **README.md** - Update when adding new features, changing public APIs, or modifying usage examples
92
+ - **Code comments** - Update inline documentation when changing method signatures or behavior
data/Gemfile CHANGED
@@ -5,10 +5,11 @@ source 'http://rubygems.org'
5
5
  gem 'inheritance-helper'
6
6
 
7
7
  group :development do
8
- gem 'rake'
9
- gem 'rubocop'
10
8
  gem 'activesupport'
9
+ gem 'rake'
11
10
  gem 'rspec'
11
+ gem 'rubocop'
12
12
  gem 'simplecov'
13
+ gem 'simplecov-cobertura'
13
14
  gem 'webmock'
14
15
  end