configly-ruby 0.0.2 → 0.0.7

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