twelvedata_ruby 0.3.0 โ 0.4.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 +4 -4
- data/.rspec +4 -0
- data/.rubocop.yml +102 -0
- data/.yardopts +14 -0
- data/CHANGELOG.md +199 -4
- data/{LICENSE.txt โ LICENSE} +1 -1
- data/README.md +392 -88
- data/Rakefile +110 -4
- data/lib/twelvedata_ruby/client.rb +137 -88
- data/lib/twelvedata_ruby/endpoint.rb +292 -242
- data/lib/twelvedata_ruby/error.rb +93 -45
- data/lib/twelvedata_ruby/request.rb +106 -33
- data/lib/twelvedata_ruby/response.rb +268 -110
- data/lib/twelvedata_ruby/utils.rb +91 -14
- data/lib/twelvedata_ruby/version.rb +6 -0
- data/lib/twelvedata_ruby.rb +41 -30
- data/twelvedata_ruby.gemspec +28 -23
- metadata +25 -143
- data/.gitignore +0 -13
- data/Gemfile +0 -6
- data/Gemfile.lock +0 -80
- data/bin/console +0 -22
- data/bin/setup +0 -8
data/README.md
CHANGED
@@ -1,9 +1,18 @@
|
|
1
1
|
# TwelvedataRuby
|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/ruby)
|
4
4
|
|
5
|
-
|
5
|
+
A Ruby client library for accessing [Twelve Data's](https://twelvedata.com) comprehensive financial API. Get real-time and historical data for stocks, forex, cryptocurrencies, ETFs, indices, and more.
|
6
6
|
|
7
|
+
## Features
|
8
|
+
|
9
|
+
- ๐ **Modern Ruby** - Requires Ruby 3.4.0+, follows modern Ruby practices
|
10
|
+
- ๐ **Comprehensive API Coverage** - All Twelve Data endpoints supported
|
11
|
+
- ๐ **Type Safety** - Strong parameter validation and error handling
|
12
|
+
- ๐ **Multiple Formats** - JSON and CSV response formats
|
13
|
+
- ๐งช **Well Tested** - 100% test coverage
|
14
|
+
- ๐ง **Developer Friendly** - Excellent error messages and debugging support
|
15
|
+
- โก **High Performance** - Built on HTTPX for concurrent requests
|
7
16
|
|
8
17
|
## Installation
|
9
18
|
|
@@ -15,142 +24,437 @@ gem 'twelvedata_ruby'
|
|
15
24
|
|
16
25
|
And then execute:
|
17
26
|
|
18
|
-
|
27
|
+
```bash
|
28
|
+
bundle install
|
29
|
+
```
|
19
30
|
|
20
31
|
Or install it yourself as:
|
21
32
|
|
22
|
-
|
33
|
+
```bash
|
34
|
+
gem install twelvedata_ruby
|
35
|
+
```
|
23
36
|
|
24
|
-
##
|
37
|
+
## Quick Start
|
25
38
|
|
26
|
-
|
39
|
+
### 1. Get Your API Key
|
27
40
|
|
28
|
-
|
41
|
+
Sign up for a free API key at [Twelve Data](https://twelvedata.com/pricing).
|
42
|
+
|
43
|
+
### 2. Basic Usage
|
29
44
|
|
30
45
|
```ruby
|
31
|
-
require
|
46
|
+
require 'twelvedata_ruby'
|
47
|
+
|
48
|
+
# Option 1: Configure with API key directly
|
49
|
+
client = TwelvedataRuby.client(apikey: "your-api-key-here")
|
50
|
+
|
51
|
+
# Option 2: Use environment variable (recommended)
|
52
|
+
ENV['TWELVEDATA_API_KEY'] = 'your-api-key-here'
|
32
53
|
client = TwelvedataRuby.client
|
54
|
+
|
55
|
+
# Get a stock quote
|
56
|
+
response = client.quote(symbol: "AAPL")
|
57
|
+
puts response.parsed_body
|
58
|
+
# => {
|
59
|
+
# symbol: "AAPL",
|
60
|
+
# name: "Apple Inc",
|
61
|
+
# exchange: "NASDAQ",
|
62
|
+
# currency: "USD",
|
63
|
+
# datetime: "2024-01-15",
|
64
|
+
# open: "185.00",
|
65
|
+
# high: "187.50",
|
66
|
+
# low: "184.20",
|
67
|
+
# close: "186.75",
|
68
|
+
# volume: "45678900",
|
69
|
+
# ...
|
70
|
+
# }
|
33
71
|
```
|
34
72
|
|
35
|
-
|
73
|
+
## API Reference
|
74
|
+
|
75
|
+
### Stock Market Data
|
36
76
|
|
37
77
|
```ruby
|
38
|
-
|
39
|
-
client.
|
40
|
-
client.
|
78
|
+
# Real-time quote
|
79
|
+
client.quote(symbol: "AAPL")
|
80
|
+
client.quote(symbol: "GOOGL", exchange: "NASDAQ")
|
81
|
+
|
82
|
+
# Current price only
|
83
|
+
client.price(symbol: "TSLA")
|
84
|
+
|
85
|
+
# Historical time series data
|
86
|
+
client.time_series(
|
87
|
+
symbol: "AAPL",
|
88
|
+
interval: "1day",
|
89
|
+
start_date: "2024-01-01",
|
90
|
+
end_date: "2024-01-31"
|
91
|
+
)
|
92
|
+
|
93
|
+
# End of day prices
|
94
|
+
client.eod(symbol: "MSFT")
|
95
|
+
|
96
|
+
# Search for symbols
|
97
|
+
client.symbol_search(symbol: "Apple")
|
41
98
|
```
|
42
99
|
|
43
|
-
|
100
|
+
### Forex & Currency
|
44
101
|
|
45
102
|
```ruby
|
46
|
-
|
47
|
-
client
|
48
|
-
|
103
|
+
# Exchange rates
|
104
|
+
client.exchange_rate(symbol: "USD/EUR")
|
105
|
+
|
106
|
+
# Currency conversion
|
107
|
+
client.currency_conversion(symbol: "USD/EUR", amount: 100)
|
108
|
+
|
109
|
+
# Available forex pairs
|
110
|
+
client.forex_pairs
|
49
111
|
```
|
50
112
|
|
51
|
-
|
113
|
+
### Cryptocurrency
|
52
114
|
|
53
|
-
|
115
|
+
```ruby
|
116
|
+
# Crypto quotes
|
117
|
+
client.quote(symbol: "BTC/USD")
|
118
|
+
|
119
|
+
# Available cryptocurrencies
|
120
|
+
client.cryptocurrencies
|
121
|
+
|
122
|
+
# Crypto exchanges
|
123
|
+
client.cryptocurrency_exchanges
|
124
|
+
```
|
125
|
+
|
126
|
+
### Market Reference Data
|
54
127
|
|
55
128
|
```ruby
|
56
|
-
#
|
57
|
-
client.
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
#
|
63
|
-
client.
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
#
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
client.price(symbol: "GOOG", invalid_parameter: "value")
|
74
|
-
```
|
75
|
-
|
76
|
-
All of the invocations possible return instance value is one of the following:
|
77
|
-
- `TwelvedataRuby::Response` instance object which `#error` instance getter method can return a nil or kind of `TwelvedataRuby::ResponseError` instance if the API, or the API web server responded with some errors. #5 is an example which the API response will have status error with 401 code. `TwelvedataRuby::Response` resolves this into `TwelvedataRuby::UnauthorizedResponseError` instance.
|
78
|
-
- `TwelvedataRuby::ResponseError` instance object itself when some error occurred that's not coming from the API
|
79
|
-
- a Hash instance which has an `:errors` key that contains instances of kind `TwelvedataRuby::EndpointError`. This is an invalid request scenario which the #7, #8, and #9 examples. No actual API request was sent in this scenario.
|
80
|
-
|
81
|
-
On first invocation of a valid endpoint name, a `TwelvedataRuby::Client` instance method of the same name is dynamically defined. So in effect, ideally, there can be a one-to-one mapping of all the API endpoints with their respective parameters constraints. Please visit their excellent API documentation to know more of the endpoint details here https://twelvedata.com/doc. Or if you're in a hurry, you can list the endpoints definitions:
|
129
|
+
# Available stocks
|
130
|
+
client.stocks(exchange: "NASDAQ")
|
131
|
+
|
132
|
+
# ETF information
|
133
|
+
client.etf
|
134
|
+
|
135
|
+
# Market indices
|
136
|
+
client.indices
|
137
|
+
|
138
|
+
# Stock exchanges
|
139
|
+
client.exchanges
|
140
|
+
|
141
|
+
# Technical indicators
|
142
|
+
client.technical_indicators
|
143
|
+
```
|
144
|
+
|
145
|
+
### Account & Usage
|
82
146
|
|
83
147
|
```ruby
|
84
|
-
|
148
|
+
# Check API usage
|
149
|
+
usage = client.api_usage
|
150
|
+
puts "Current usage: #{usage.parsed_body[:current_usage]}/#{usage.parsed_body[:plan_limit]}"
|
85
151
|
```
|
86
152
|
|
87
|
-
|
153
|
+
## Advanced Usage
|
154
|
+
|
155
|
+
### Response Formats
|
88
156
|
|
89
157
|
```ruby
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
158
|
+
# JSON response (default)
|
159
|
+
response = client.quote(symbol: "AAPL", format: :json)
|
160
|
+
data = response.parsed_body # Hash
|
161
|
+
|
162
|
+
# CSV response
|
163
|
+
response = client.quote(symbol: "AAPL", format: :csv)
|
164
|
+
table = response.parsed_body # CSV::Table
|
165
|
+
|
166
|
+
# Save CSV to file
|
167
|
+
response = client.time_series(
|
168
|
+
symbol: "AAPL",
|
169
|
+
interval: "1day",
|
170
|
+
format: :csv,
|
171
|
+
filename: "apple_daily.csv"
|
172
|
+
)
|
173
|
+
response.save_to_file("./data/apple_data.csv")
|
98
174
|
```
|
99
175
|
|
100
|
-
|
176
|
+
### Error Handling
|
101
177
|
|
102
178
|
```ruby
|
103
|
-
|
104
|
-
|
179
|
+
response = client.quote(symbol: "INVALID")
|
180
|
+
|
181
|
+
if response.error
|
182
|
+
case response.error
|
183
|
+
when TwelvedataRuby::UnauthorizedResponseError
|
184
|
+
puts "Invalid API key"
|
185
|
+
when TwelvedataRuby::NotFoundResponseError
|
186
|
+
puts "Symbol not found"
|
187
|
+
when TwelvedataRuby::TooManyRequestsResponseError
|
188
|
+
puts "Rate limit exceeded"
|
189
|
+
else
|
190
|
+
puts "Error: #{response.error.message}"
|
191
|
+
end
|
192
|
+
else
|
193
|
+
puts response.parsed_body
|
194
|
+
end
|
105
195
|
```
|
106
196
|
|
107
|
-
|
197
|
+
### Configuration Options
|
108
198
|
|
199
|
+
```ruby
|
200
|
+
client = TwelvedataRuby.client(
|
201
|
+
apikey: "your-api-key",
|
202
|
+
connect_timeout: 5000, # milliseconds
|
203
|
+
apikey_env_var_name: "CUSTOM_API_KEY_VAR"
|
204
|
+
)
|
205
|
+
|
206
|
+
# Update configuration later
|
207
|
+
client.configure(connect_timeout: 10000)
|
208
|
+
|
209
|
+
# Or set individual options
|
210
|
+
client.apikey = "new-api-key"
|
211
|
+
client.connect_timeout = 3000
|
212
|
+
```
|
109
213
|
|
110
|
-
|
214
|
+
### Concurrent Requests
|
111
215
|
|
112
216
|
```ruby
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
:
|
117
|
-
:
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
:
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
:fifty_two_week=>{:low=>"1406.55005", :high=>"2659.91992", :low_change=>"1218.78003", :high_change=>"-34.58984", :low_change_percent=>"86.65031", :high_change_percent=>"-1.30041", :range=>"1406.550049 - 2659.919922"}}
|
130
|
-
```
|
131
|
-
|
132
|
-
Likewise, if the API request format is `:csv` then `Response#parsed_body` will be `CSV#Table` instance
|
217
|
+
# Create multiple requests
|
218
|
+
requests = [
|
219
|
+
TwelvedataRuby::Request.new(:quote, symbol: "AAPL"),
|
220
|
+
TwelvedataRuby::Request.new(:quote, symbol: "GOOGL"),
|
221
|
+
TwelvedataRuby::Request.new(:quote, symbol: "MSFT")
|
222
|
+
]
|
223
|
+
|
224
|
+
# Send them concurrently
|
225
|
+
responses = TwelvedataRuby::Client.request(requests)
|
226
|
+
responses.each_with_index do |http_response, index|
|
227
|
+
response = TwelvedataRuby::Response.resolve(http_response, requests[index])
|
228
|
+
puts "#{requests[index].query_params[:symbol]}: #{response.parsed_body[:close]}"
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
### Complex Data Queries
|
133
233
|
|
134
234
|
```ruby
|
135
|
-
|
136
|
-
|
235
|
+
# POST request for complex data
|
236
|
+
response = client.complex_data(
|
237
|
+
symbols: "AAPL,GOOGL,MSFT",
|
238
|
+
intervals: "1day,1week",
|
239
|
+
start_date: "2024-01-01",
|
240
|
+
end_date: "2024-01-31",
|
241
|
+
methods: "time_series"
|
242
|
+
)
|
243
|
+
```
|
244
|
+
|
245
|
+
## Response Objects
|
246
|
+
|
247
|
+
### Response Methods
|
248
|
+
|
249
|
+
```ruby
|
250
|
+
response = client.quote(symbol: "AAPL")
|
251
|
+
|
252
|
+
# Response status
|
253
|
+
response.success? # => true/false
|
254
|
+
response.http_status_code # => 200
|
255
|
+
response.status_code # => API status code
|
256
|
+
|
257
|
+
# Content information
|
258
|
+
response.content_type # => :json, :csv, :plain
|
259
|
+
response.body_bytesize # => response size in bytes
|
260
|
+
|
261
|
+
# Parsed data
|
262
|
+
response.parsed_body # => Hash, CSV::Table, or String
|
263
|
+
response.body # => alias for parsed_body
|
264
|
+
|
265
|
+
# Error information
|
266
|
+
response.error # => nil or ResponseError instance
|
267
|
+
|
268
|
+
# File operations
|
269
|
+
response.attachment_filename # => "filename.csv" if present
|
270
|
+
response.save_to_file("path/to/file.csv")
|
271
|
+
response.dump_parsed_body # => serialized content
|
272
|
+
|
273
|
+
# Debugging
|
274
|
+
response.to_s # => human-readable summary
|
275
|
+
response.inspect # => detailed inspection
|
276
|
+
```
|
277
|
+
|
278
|
+
### Error Types
|
279
|
+
|
280
|
+
```ruby
|
281
|
+
# Base error types
|
282
|
+
TwelvedataRuby::Error # Base error class
|
283
|
+
TwelvedataRuby::ConfigurationError # Configuration issues
|
284
|
+
TwelvedataRuby::NetworkError # Network connectivity issues
|
285
|
+
|
286
|
+
# API endpoint errors
|
287
|
+
TwelvedataRuby::EndpointError # Invalid endpoint usage
|
288
|
+
TwelvedataRuby::EndpointNameError # Invalid endpoint name
|
289
|
+
TwelvedataRuby::EndpointParametersKeysError # Invalid parameters
|
290
|
+
TwelvedataRuby::EndpointRequiredParametersError # Missing required parameters
|
291
|
+
|
292
|
+
# API response errors
|
293
|
+
TwelvedataRuby::ResponseError # Base response error
|
294
|
+
TwelvedataRuby::BadRequestResponseError # 400 errors
|
295
|
+
TwelvedataRuby::UnauthorizedResponseError # 401 errors
|
296
|
+
TwelvedataRuby::ForbiddenResponseError # 403 errors
|
297
|
+
TwelvedataRuby::NotFoundResponseError # 404 errors
|
298
|
+
TwelvedataRuby::TooManyRequestsResponseError # 429 errors
|
299
|
+
TwelvedataRuby::InternalServerResponseError # 500 errors
|
300
|
+
```
|
301
|
+
|
302
|
+
## Available Endpoints
|
303
|
+
|
304
|
+
| Endpoint | Method | Required Parameters | Description |
|
305
|
+
| -------------------------- | ------ | ------------------------------------------------ | -------------------------- |
|
306
|
+
| `quote` | GET | `symbol` | Real-time stock quote |
|
307
|
+
| `price` | GET | `symbol` | Current stock price |
|
308
|
+
| `time_series` | GET | `symbol`, `interval` | Historical price data |
|
309
|
+
| `eod` | GET | `symbol` | End of day price |
|
310
|
+
| `exchange_rate` | GET | `symbol` | Forex exchange rate |
|
311
|
+
| `currency_conversion` | GET | `symbol`, `amount` | Currency conversion |
|
312
|
+
| `symbol_search` | GET | `symbol` | Search for symbols |
|
313
|
+
| `earliest_timestamp` | GET | `symbol`, `interval` | Earliest available data |
|
314
|
+
| `api_usage` | GET | - | API usage statistics |
|
315
|
+
| `stocks` | GET | - | Available stocks |
|
316
|
+
| `forex_pairs` | GET | - | Available forex pairs |
|
317
|
+
| `cryptocurrencies` | GET | - | Available cryptocurrencies |
|
318
|
+
| `etf` | GET | - | Available ETFs |
|
319
|
+
| `indices` | GET | - | Available indices |
|
320
|
+
| `exchanges` | GET | - | Available exchanges |
|
321
|
+
| `cryptocurrency_exchanges` | GET | - | Available crypto exchanges |
|
322
|
+
| `technical_indicators` | GET | - | Available indicators |
|
323
|
+
| `earnings` | GET | `symbol` | Earnings data |
|
324
|
+
| `earnings_calendar` | GET | - | Earnings calendar |
|
325
|
+
| `complex_data` | POST | `symbols`, `intervals`, `start_date`, `end_date` | Complex data queries |
|
326
|
+
|
327
|
+
For complete parameter documentation, visit [Twelve Data's API documentation](https://twelvedata.com/docs).
|
328
|
+
|
329
|
+
## Development
|
330
|
+
|
331
|
+
### Running Tests
|
332
|
+
|
333
|
+
```bash
|
334
|
+
# Run all tests
|
335
|
+
bundle exec rspec
|
336
|
+
|
337
|
+
# Run with coverage
|
338
|
+
COVERAGE=true bundle exec rspec
|
339
|
+
|
340
|
+
# Run specific test file
|
341
|
+
bundle exec rspec spec/lib/twelvedata_ruby/client_spec.rb
|
342
|
+
|
343
|
+
# Run with profile information
|
344
|
+
PROFILE=true bundle exec rspec
|
345
|
+
```
|
346
|
+
|
347
|
+
### Code Quality
|
348
|
+
|
349
|
+
```bash
|
350
|
+
# Run RuboCop
|
351
|
+
bundle exec rubocop
|
352
|
+
|
353
|
+
# Auto-fix issues
|
354
|
+
bundle exec rubocop -A
|
355
|
+
|
356
|
+
# Generate documentation
|
357
|
+
bundle exec yard doc
|
358
|
+
```
|
359
|
+
|
360
|
+
### Debugging
|
361
|
+
|
362
|
+
```ruby
|
363
|
+
# Enable debugging output
|
364
|
+
require 'pry'
|
365
|
+
|
366
|
+
client = TwelvedataRuby.client(apikey: "your-key")
|
367
|
+
response = client.quote(symbol: "AAPL")
|
368
|
+
|
369
|
+
# Debug response
|
370
|
+
binding.pry
|
371
|
+
|
372
|
+
# Inspect request details
|
373
|
+
puts response.request.to_h
|
374
|
+
puts response.request.full_url
|
375
|
+
puts response.request.query_params
|
137
376
|
```
|
138
377
|
|
139
|
-
## Documentation
|
140
|
-
You can browse the source code [documentation](https://kanroyalhigh.github.io/twelvedata_ruby/doc/)
|
141
378
|
## Contributing
|
142
379
|
|
143
|
-
|
380
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
381
|
+
|
382
|
+
1. Fork the repository
|
383
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
384
|
+
3. Make your changes with tests
|
385
|
+
4. Run the test suite (`bundle exec rspec`)
|
386
|
+
5. Run RuboCop (`bundle exec rubocop`)
|
387
|
+
6. Commit your changes (`git commit -am 'Add amazing feature'`)
|
388
|
+
7. Push to the branch (`git push origin feature/amazing-feature`)
|
389
|
+
8. Open a Pull Request
|
390
|
+
|
391
|
+
## Release Process
|
392
|
+
|
393
|
+
#### Quick Release Guide
|
394
|
+
|
395
|
+
```bash
|
396
|
+
# 1. Prepare release
|
397
|
+
bin/release prepare --version 0.4.1
|
398
|
+
|
399
|
+
# 2. Push changes
|
400
|
+
git push origin main
|
401
|
+
|
402
|
+
# 3. Create GitHub release with tag v0.4.1
|
403
|
+
# โ Automatic publication to RubyGems.org via GitHub Actions
|
404
|
+
```
|
405
|
+
|
406
|
+
#### Release Helper Commands
|
407
|
+
|
408
|
+
```bash
|
409
|
+
# Check if ready for release
|
410
|
+
bin/release check
|
411
|
+
|
412
|
+
# Auto-bump version
|
413
|
+
bin/release bump --type patch # 0.4.0 โ 0.4.1
|
414
|
+
bin/release bump --type minor # 0.4.0 โ 0.5.0
|
415
|
+
bin/release bump --type major # 0.4.0 โ 1.0.0
|
416
|
+
|
417
|
+
# Dry run (test without changes)
|
418
|
+
bin/release prepare --version 0.4.1 --dry-run
|
419
|
+
```
|
420
|
+
|
421
|
+
#### GitHub Workflows
|
422
|
+
|
423
|
+
- **CI**: Runs tests, linting, and security scans on every push/PR
|
424
|
+
- **Release**: Automatically publishes to RubyGems.org when GitHub release is created
|
425
|
+
- **Documentation**: Updates GitHub Pages with latest API docs
|
426
|
+
|
427
|
+
#### Manual Release (Advanced)
|
428
|
+
|
429
|
+
```bash
|
430
|
+
# Trigger release workflow manually
|
431
|
+
gh workflow run release.yml \
|
432
|
+
--field version=0.4.1 \
|
433
|
+
--field dry_run=false
|
434
|
+
```
|
144
435
|
|
145
436
|
## License
|
146
437
|
|
147
|
-
|
438
|
+
This gem is available as open source under the terms of the [MIT License](LICENSE).
|
148
439
|
|
149
440
|
## Code of Conduct
|
150
441
|
|
151
|
-
Everyone interacting in the TwelvedataRuby project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](
|
442
|
+
Everyone interacting in the TwelvedataRuby project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](CODE_OF_CONDUCT.md).
|
443
|
+
|
444
|
+
## Support
|
445
|
+
|
446
|
+
- ๐ [API Documentation](https://kanutocd.github.io/twelvedata_ruby/doc/)
|
447
|
+
- ๐ [Issue Tracker](https://github.com/kanutocd/twelvedata_ruby/issues)
|
448
|
+
- ๐ง Email: kenneth.c.demanawa@gmail.com
|
449
|
+
|
450
|
+
## Changelog
|
451
|
+
|
452
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history and changes.
|
453
|
+
|
454
|
+
## Notice
|
152
455
|
|
456
|
+
This is not an official Twelve Data Ruby library. The author of this gem is not affiliated with Twelve Data in any way, shape or form. Twelve Data APIs and data are Copyright ยฉ 2024 Twelve Data Pte. Ltd.
|
153
457
|
|
154
|
-
|
458
|
+
---
|
155
459
|
|
156
|
-
|
460
|
+
**Made with โค๏ธ by the Ruby community**
|
data/Rakefile
CHANGED
@@ -2,11 +2,117 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
|
+
require "rubocop/rake_task"
|
5
6
|
|
6
|
-
RSpec
|
7
|
+
# RSpec tasks
|
8
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
9
|
+
task.rspec_opts = [
|
10
|
+
"--format", "progress",
|
11
|
+
"--color",
|
12
|
+
"--require", "spec_helper"
|
13
|
+
]
|
14
|
+
end
|
7
15
|
|
8
|
-
|
16
|
+
# RuboCop tasks
|
17
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
18
|
+
task.options = ["--display-cop-names"]
|
19
|
+
end
|
20
|
+
|
21
|
+
RuboCop::RakeTask.new("rubocop:auto_correct") do |task|
|
22
|
+
task.options = ["--auto-correct"]
|
23
|
+
end
|
24
|
+
|
25
|
+
# Quality assurance task
|
26
|
+
desc "Run all quality checks"
|
27
|
+
task :qa do
|
28
|
+
puts "๐ Running RuboCop..."
|
29
|
+
Rake::Task["rubocop"].invoke
|
30
|
+
|
31
|
+
puts "\n๐งช Running tests..."
|
32
|
+
Rake::Task["spec"].invoke
|
33
|
+
|
34
|
+
puts "\nโ
All quality checks passed!"
|
35
|
+
rescue SystemExit => e
|
36
|
+
puts "\nโ Quality checks failed!"
|
37
|
+
exit e.status
|
38
|
+
end
|
39
|
+
|
40
|
+
# Documentation tasks
|
41
|
+
begin
|
42
|
+
require "yard"
|
43
|
+
|
44
|
+
YARD::Rake::YardocTask.new(:doc) do |task|
|
45
|
+
task.files = ["lib/**/*.rb"]
|
46
|
+
task.options = [
|
47
|
+
"--markup", "markdown",
|
48
|
+
"--markup-provider", "kramdown",
|
49
|
+
"--main", "README.md",
|
50
|
+
"--output-dir", "doc"
|
51
|
+
]
|
52
|
+
end
|
53
|
+
|
54
|
+
desc "Generate and open documentation"
|
55
|
+
task docs: :doc do
|
56
|
+
system("open doc/index.html") if RUBY_PLATFORM.include?("darwin")
|
57
|
+
end
|
58
|
+
rescue LoadError
|
59
|
+
puts "YARD not available. Install it with: gem install yard"
|
60
|
+
end
|
61
|
+
|
62
|
+
# Coverage task
|
63
|
+
desc "Run tests with coverage report"
|
64
|
+
task :coverage do
|
65
|
+
ENV["COVERAGE"] = "true"
|
66
|
+
Rake::Task["spec"].invoke
|
67
|
+
end
|
68
|
+
|
69
|
+
# Development setup task
|
70
|
+
desc "Set up development environment"
|
71
|
+
task :setup do
|
72
|
+
puts "๐ฆ Installing dependencies..."
|
73
|
+
system("bundle install")
|
74
|
+
|
75
|
+
puts "๐ง Setting up git hooks..."
|
76
|
+
setup_git_hooks
|
77
|
+
|
78
|
+
puts "โ
Development environment ready!"
|
79
|
+
end
|
80
|
+
|
81
|
+
# Release preparation task
|
82
|
+
desc "Prepare for release"
|
83
|
+
task :release_prep do
|
84
|
+
puts "๐ Running quality checks..."
|
85
|
+
Rake::Task["qa"].invoke
|
86
|
+
|
87
|
+
puts "๐ Generating documentation..."
|
88
|
+
Rake::Task["doc"].invoke if defined?(YARD)
|
89
|
+
|
90
|
+
puts "โ
Ready for release!"
|
91
|
+
end
|
92
|
+
|
93
|
+
# Console task for development
|
94
|
+
desc "Start interactive console with gem loaded"
|
95
|
+
task :console do
|
96
|
+
require "irb"
|
97
|
+
require "twelvedata_ruby"
|
98
|
+
ARGV.clear
|
99
|
+
IRB.start
|
100
|
+
end
|
101
|
+
|
102
|
+
# Default task
|
103
|
+
task default: :qa
|
104
|
+
|
105
|
+
# Helper methods
|
106
|
+
def setup_git_hooks
|
107
|
+
hooks_dir = File.join(__dir__, ".git", "hooks")
|
108
|
+
return unless Dir.exist?(hooks_dir)
|
9
109
|
|
10
|
-
|
110
|
+
pre_commit_hook = File.join(hooks_dir, "pre-commit")
|
111
|
+
File.write(pre_commit_hook, <<~HOOK)
|
112
|
+
#!/bin/sh
|
113
|
+
echo "Running pre-commit checks..."
|
114
|
+
bundle exec rubocop --format simple
|
115
|
+
HOOK
|
11
116
|
|
12
|
-
|
117
|
+
File.chmod(0o755, pre_commit_hook) if File.exist?(pre_commit_hook)
|
118
|
+
end
|