configly-ruby 0.0.2 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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