configly-ruby 0.0.5 → 0.0.6

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: 524b5942925d1b420aca59131590986ca941ac9206e543ad00448fd1e303d0c0
4
- data.tar.gz: 679cc9958ff99e8eea95fc13c713074ef880d43aaf684679d8d80f4a7a00043b
3
+ metadata.gz: 5d1525cdf4c14061d87df93eb5d7784ed7ec17a97ca73952c1b05955c22c1d89
4
+ data.tar.gz: e5e66c9d611800617304884ec26a408cd4e900f7ce559e38998e1126650098b2
5
5
  SHA512:
6
- metadata.gz: 97445a7db758cbc30d2f49aaf14736855276d2195cd808e199d6b2f1a395edfc2a4503e9ef6381c6fef2a8d18e94bda89a69b2bfa38a1a8aa06c5192a1746a38
7
- data.tar.gz: 3604454a283d703dc3b0a563e4c497cfaa85208b92c5124183259165bb121c441d2c7e6b468eb22e5ab7bc58c6c5b8e209957148cadc9bf1cc7bb986d36731c7
6
+ metadata.gz: 9ccd504f03c7a4f08242b887d873d7e47588cc3fbcb7258c0dc299828b3f982724520451c0f14cd8725d0df1436a787ab9bf076b7da33c8a32ec1d9bab620931
7
+ data.tar.gz: 90e29d3e9c06d3292f9f1470275567a9bec65d3e6f157b79d223a9d811e53983848db69fb80d8c3d553ef029eeaa337acdcd8e36596592492e7ed3e2d990ccac
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Configly React Library
1
+ # Configly Ruby Library
2
2
  > The Ruby library for [Configly](https://www.config.ly): the modern config/static data key/value store.
3
3
 
4
- ![npm](https://img.shields.io/npm/v/configly-react)
5
- ![GitHub](https://img.shields.io/github/license/configly/react)
4
+ ![npm](https://img.shields.io/gem/v/configly-ruby)
5
+ ![GitHub](https://img.shields.io/github/license/configly/ruby)
6
6
 
7
7
  Table of Contents
8
8
  =================
@@ -38,13 +38,73 @@ read more about the benefits at [Configly](config.ly).
38
38
 
39
39
  - API to fetch Strings, JSON Blobs (arrays and objects), Booleans, and Numbers from the Configly backend
40
40
  - [Web interface](https://www.config.ly/config) for modifying these values without having to deploy code (we call our beloved web interface _the Configulator_).
41
- - High availability, high-throughput, low-latency backend.
42
- - Smart caching on the client libraries to minimize server requests.
41
+ - High availability, high-throughput, low-latency backend.
43
42
  - Client libraries available in an expanding amount of languages.
44
43
 
44
+ ### Concepts/ Data Model
45
+ - A Configly account contains a set of Configs.
46
+ - A Config is a key-value pair along with associated metadata (like TTL).
47
+ - The keys are strings.
48
+ - The values are one of the following types:
49
+
50
+ #### Types
51
+
52
+ | Type | notes | Example(s)|
53
+ |---------|----------|----------|
54
+ | string | | "I <3 Configly!" |
55
+ | number | Can be integers or decimal; _be aware some clients require you to specify which when fetching_ | 31337, 1.618 |
56
+ | boolean | only true or false | true, false |
57
+ | jsonBlob | A [JSON5](https://json5.org/) (more relaxed JSON) array or object. | ``` ["one", 5, true]```, ```{"text": "Buy now!", color: "#0F0"}``` |
58
+
59
+ ##### More `jsonBlob` examples
60
+ You can make arbitrarily complex JSON structures -- _as long_ as the top level is
61
+ an object or array. This is incredibly powerful as you can send a host of data
62
+ with a single _config_:
63
+
64
+
65
+ A more complex array for a store inventory. Note that because we're using JSON5, quotes
66
+ are optional for single words.
67
+ ```js
68
+ [
69
+ "Simple T-shirt",
70
+ "Basic hoodie",
71
+ {
72
+ item: "Complex T-shirt",
73
+ sizes: ['S', 'M', 'L'],
74
+ price_us_cents: [1099, 1499, 1599],
75
+ }
76
+ ]
77
+ ```
78
+
79
+ And a more complex object showing how you can internationalize and set style:
80
+ ```js
81
+ {
82
+ "welcome_message": {
83
+ copy: {
84
+ 'en': 'Welcome!',
85
+ 'es': "¡Bienvenidos!",
86
+ }, style: {
87
+ color: '#0F0',
88
+ fontWeight: '700',
89
+ }
90
+ },
91
+ "buy_button" : {
92
+ copy: {
93
+ 'en': 'Buy',
94
+ 'es': "Comprar",
95
+ }, style: {
96
+ backgroundColor: "#F00",
97
+ border: "border-radius 10px",
98
+ }
99
+ }
100
+ }
101
+ ```
102
+
45
103
  ## Getting Started
46
104
 
47
- ### Get your API Key
105
+ In four easy steps!
106
+
107
+ ### 1. Get your API Key
48
108
 
49
109
  You'll need a [Configly](https://www.config.ly) account. Registration is lightning quick&mdash;you can register via
50
110
  visiting [https://www.config.ly/signup](https://www.config.ly/signup).
@@ -52,27 +112,115 @@ visiting [https://www.config.ly/signup](https://www.config.ly/signup).
52
112
  After signing up, you can grab your API Key from [https://www.config.ly/register](https://www.config.ly/register).
53
113
  You'll need your API Key to setup the API below.
54
114
 
55
- ### Library Installation
115
+ ### 2. Create your first Config
116
+ From [https://www.config.ly/config](https://www.config.ly/config), create a new Config via the "Add" button:
117
+ ![image](https://user-images.githubusercontent.com/184923/98487495-3b42ca80-21f1-11eb-9bfc-bfd429733362.png)
118
+
119
+ Consider creating a simple `JSON Object or Array` Config called `greetings` and give it the value of:
120
+ `['hello', 'hola', '你好', 'नमस्ते']`:
121
+
122
+ [https://www.config.ly/config](https://www.config.ly/config) should look like this:
123
+
124
+ ![image](https://user-images.githubusercontent.com/184923/98494454-09d6f880-220b-11eb-9ef7-36709ddc129f.png)
56
125
 
126
+ Be sure to save via clicking 'Send to Clients'. Now, we'll write client code to fetch this key.
127
+
128
+ ### 3. Install the client library
129
+
130
+ If you're using bundler, add the following line to your project's `Gemfile`:
131
+ ```sh
132
+ gem 'configly-ruby', '~> 0.0.5'
133
+ ```
134
+
135
+ Or, if you're using the Gem directly from your application, you can run:
57
136
  ```sh
58
137
  gem install configly-ruby
59
138
  ```
60
139
 
61
140
  You will need to set the `CONFIGLY_API_KEY` environment variable.
62
141
 
63
- ### Using this library with websockets
142
+ ### 4. Fetch the Config
143
+ In a Rails controller, add the following code
144
+ ```ruby
145
+ def get
146
+ begin
147
+ key = Configly::Client.get(params[:key])
148
+ render plain: key
149
+ rescue Configly::KeyError
150
+ render :status => 404
151
+ end
152
+ end
153
+ ```
154
+
155
+ Map the route, and then request it in your browser with the `key` params (e.g. `http://localhost:3000/configly?key=test1234`).
156
+
157
+ Try changing some values on [https://www.config.ly/config](https://www.config.ly/config) to confirm that
158
+ the client is getting the updates.
159
+
160
+ Congratulations you have Configly working end-to-end! Now, feel free to use Configly with all your projects!
161
+
162
+ ## Configuring this library to use websockets
64
163
  Coming soon...
65
164
 
66
165
  ## Usage
166
+ > The golden rule of Configly library use is: **do NOT** assign the result of a `get()`
167
+ to a long-lived variable; in order to check for new values from the server, you must call `get()`.
168
+
169
+ The package needs to be configured with your account's API key, which is available in the
170
+ [Configly Configulator](https://config.ly/config)
171
+
172
+ ```
173
+ // This value is stored on the Config.ly servers.
174
+ store_catalog:
175
+ {
176
+ has_sale: true,
177
+ discount: 0.8,
178
+ items: ['T Shirt', 'Hoodie', 'Ferrari'],
179
+ price: [ 100, 250, 200000],
180
+ }
181
+ ```
67
182
 
68
- To fetch a key, use the following command:
183
+ On the Ruby client:
69
184
 
70
185
  ```ruby
71
- Configly::Client.get(KEY)
186
+ begin
187
+ catalog = Configly::Client.get(KEY)
188
+ items = catalog['items']
189
+ prices = catalog['prices']
190
+
191
+ items.each_with_index do |item, index|
192
+ Rails.logger.debug("#{item}: #{prices[index]} USD")
193
+ end
194
+ rescue Configly::KeyError
195
+ Rails.logger.error("Something went wrong")
196
+ end
72
197
  ```
73
198
 
74
- If the key doesn't exist (or if you are using the websockets client and it hasn't been prefetched), this will rais a `Configly::KeyError`
199
+ Note: If the key doesn't exist, this will raise a `Configly::KeyError`
200
+
201
+ Here is an example with feature flags.
202
+ // These values are stored on the Config.ly server
203
+ ```
204
+ feature1_enabled: true
205
+ feature2_enabled: false
206
+ ```
207
+
208
+ On the ruby client:
209
+
210
+ ```ruby
211
+ begin
212
+ if Configly::Client.get('feature1_enabled')
213
+ # Logic for feature 1
214
+ end
215
+
216
+ if Configly::Client.get('feature2_enabled')
217
+ # Logic for feature 2
218
+ end
219
+ rescue Configly::KeyError
220
+ Rails.logger.error("Something went wrong")
221
+ end
222
+ ```
75
223
 
76
224
  ## License
77
225
 
78
- This repository is published under the [MIT](LICENSE.md) license.
226
+ This repository is published under the [MIT](LICENSE.md) license.
@@ -3,7 +3,7 @@ require_relative 'lib/configly/version'
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'configly-ruby'
6
- s.version = '0.0.5'
6
+ s.version = '0.0.6'
7
7
  s.date = '2020-11-16'
8
8
  s.summary = "Configly"
9
9
  s.description = "Configly SDK gem"
@@ -8,7 +8,7 @@ CONFIGLY_VALUE_URL = '/api/v1/value'
8
8
  module Configly
9
9
  class Client
10
10
  @keys = {}
11
- @caches = {}
11
+ @ttl_expirations = {}
12
12
  @use_ws = false
13
13
  def self.init
14
14
  @use_ws = true
@@ -31,7 +31,7 @@ module Configly
31
31
  end
32
32
 
33
33
  def self.load_initial_data
34
- @keys = fetch(get_keys_to_preload)
34
+ fetch(get_keys_to_preload, false)
35
35
  end
36
36
 
37
37
  def self.start_web_socket_client
@@ -62,19 +62,38 @@ module Configly
62
62
  end
63
63
  end
64
64
 
65
- def self.fetch(keys)
66
- uri = URI("https://#{CONFIGLY_SERVER}#{CONFIGLY_VALUE_URL}?#{generate_qs(keys)}")
67
- loaded_keys = {}
68
- Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
69
- request = Net::HTTP::Get.new uri
70
- request.basic_auth get_api_key, ''
71
- response = http.request request
72
- data = JSON.parse(response.body)['data']
73
- data.keys.each do |key|
74
- loaded_keys[key] = data[key]['value']
65
+ def self.fetch(keys, use_ttls)
66
+ current_time = Time.now.to_i
67
+
68
+ # If we aren't using the TTLs, fetch all keys
69
+ if !use_ttls
70
+ keys_to_fetch = keys
71
+ else
72
+ # Otherwise, fetch the keys that are unfetched or expired
73
+ keys_to_fetch = []
74
+ keys.each do |key|
75
+ if !@ttl_expirations.has_key?(key) || @ttl_expirations[key] < current_time
76
+ keys_to_fetch << key
77
+ end
78
+ end
79
+ end
80
+
81
+ # Only actually execute the request if there are keys to fetch
82
+ if keys_to_fetch.length > 0
83
+ uri = URI("https://#{CONFIGLY_SERVER}#{CONFIGLY_VALUE_URL}?#{generate_qs(keys_to_fetch)}")
84
+
85
+ Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
86
+ request = Net::HTTP::Get.new uri
87
+ request.basic_auth get_api_key, ''
88
+ response = http.request request
89
+ data = JSON.parse(response.body)['data']
90
+ data.keys.each do |key|
91
+ # Set the key and the expiration
92
+ @keys[key] = data[key]['value']
93
+ @ttl_expirations[key] = current_time + data[key]['ttl']
94
+ end
75
95
  end
76
96
  end
77
- return loaded_keys
78
97
  end
79
98
 
80
99
  def self.get(key)
@@ -85,9 +104,9 @@ module Configly
85
104
  raise KeyError.new(key)
86
105
  end
87
106
  else
88
- loaded_keys = fetch([key])
89
- if loaded_keys.has_key? key
90
- return loaded_keys[key]
107
+ fetch([key], true)
108
+ if @keys.has_key? key
109
+ return @keys[key]
91
110
  else
92
111
  raise KeyError.new(key)
93
112
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: configly-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dana Levine