text-interpolator 1.0.5 → 1.1.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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MjVjNjkyZGJhOTY1MWYwMTNhYzc0NzkyNzQzODE4YTBlZDlhY2IxMQ==
4
+ MGI1Y2YyNjFlYzEwZDEzNTJiMDhjNDNiNGJjNzBkYjI5N2M3OGVjYQ==
5
5
  data.tar.gz: !binary |-
6
- NmI4OTA5MDAxOGNjYTQ2ZjVkYjY4ZWJhM2NkZGRkMTdlNzllY2U2Mw==
6
+ YzgyYzU5Zjc4MDQzZWFkZjBkYTUxZGNmZTExZmM5YjU2MjJjOGE3Mw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- OTI4NWQxNzkxYzE1NjRiOTgzOTZkNDU1ZDQ2MDlkMmNjZTZhZjhjMDhmODRh
10
- NDkzOTE4NWY3MDcxYjgxYThiZTJmNGY1ZDAyOGMxZjFkZGFhZDhjZmMzNThj
11
- MmVhZDY3MGQ3MDdlNjNkYTRmOTM1MTg2N2IwZTNkMjJhZDQ2YWE=
9
+ MzU2YjQ5MGQ2YWY4MWU2NTY3ZDg4ZWM4OTQ3MjUwZGRhMDc4ODE2ZGQwZGQ0
10
+ YzY0Y2ZmNTc0ZmU4YTg1MjI2NzhmOTMyMDFkM2QyZDE5YTYyZGI2YWE5ZmQz
11
+ NmQ2ZmVhOTQwMGU4NjE3NzIxZmIzYTNjYzc1MTE2N2E3ODY1N2Q=
12
12
  data.tar.gz: !binary |-
13
- NTBhNGExODJkMDZjNjc3MDM2NWFjMjkxYmM4Njg0NGQzNjZkNTVmYjNlZTVk
14
- ZjBiYjE4YjhkMWMyMDNhNDcyNjk0NTU3YzE3YTIxZjc3YzEzZDY2ZGU4NGI3
15
- NWY4ZTUyN2RlYzhjNjc3OWFhYmU1NDcyOTgxYTI0ODQ2YTQ3Njg=
13
+ ZGU0YzEyNTFhNmJmMzQxYWI0NTUzZmI1MzA0ZWJlOGZhMjBjNGMxOWE3MTBm
14
+ ODA1MDE0ZDI1ZTU0MGVkMTM2OGU3YmE4ZjE1NmEwOGFkYjkxMmI3NzQ0NDMy
15
+ YjQ0N2U2MjIzYzM2ZmI1ZGQ2ZjZkOGViOTFlOTQyMzNkNjdiOWQ=
@@ -0,0 +1,14 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectCodeStyleSettingsManager">
4
+ <option name="PER_PROJECT_SETTINGS">
5
+ <value>
6
+ <XML>
7
+ <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
8
+ </XML>
9
+ </value>
10
+ </option>
11
+ <option name="PREFERRED_PROJECT_CODE_STYLE" value="alex" />
12
+ </component>
13
+ </project>
14
+
data/CHANGES CHANGED
@@ -22,4 +22,8 @@
22
22
 
23
23
  == Version 1.0.5
24
24
 
25
- * Bug fix.
25
+ * Bug fix.
26
+
27
+ == Version 1.1.0
28
+
29
+ * Adding qualified variable names.
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  You have few options in ruby for variables interpolation:
6
6
 
7
- - interpolation inside string:
7
+ - interpolation inside the string:
8
8
 
9
9
  ```ruby
10
10
  var1 = 'some value 1'
@@ -36,9 +36,9 @@ result = template.result(binding)
36
36
  puts result # We have var1: some value 1 and var2: some value 2.
37
37
  ```
38
38
 
39
- This library can be used for interpolation inside file with string syntax.
39
+ This library can be used for **interpolation inside file with string syntax**.
40
40
 
41
- In order to achieve it uses this ruby trick:
41
+ In order to achieve it library uses this ruby trick:
42
42
 
43
43
  ```ruby
44
44
  env = {var1: 'some value 1', var2: 'some value 2'}
@@ -58,12 +58,20 @@ It's straightforward:
58
58
  # some_template.txt
59
59
 
60
60
  We have var1: #{var1} and var2: #{var2}.
61
+ We have var3: #{settings.var3} and var4: #{settings.var4}.
61
62
 
62
63
  # test.rb
63
64
 
64
65
  require 'text_interpolator'
65
66
 
66
- env ={var1: 'some value 1', var2: 'some value 2'}
67
+ env = {
68
+ var1: 'some value 1',
69
+ var2: 'some value 2',
70
+ settings: {
71
+ var3: 'some value 3',
72
+ var4: 'some value 4'
73
+ }
74
+ }
67
75
 
68
76
  template = File.read("some_template.txt")
69
77
 
@@ -72,4 +80,5 @@ text_interpolator = TextInterpolator.new
72
80
  result = text_interpolator.interpolate template, env
73
81
 
74
82
  puts result # We have var1: some value 1 and var2: some value 2.
83
+ # We have var3: some value 3 and var4: some value 4.
75
84
  ```
@@ -0,0 +1,125 @@
1
+ require 'singleton'
2
+
3
+ class HashProcessor
4
+ include Singleton
5
+
6
+ def process hash
7
+ errors = {}
8
+
9
+ content = interpolate_system_variables(hash)
10
+
11
+ var_table = build_variables_table(content) # one-dimensional collection of variables
12
+
13
+ result = interpolate_variables(content, var_table, errors)
14
+
15
+ [result, errors]
16
+ end
17
+
18
+ private
19
+
20
+ def interpolate_system_variables hash
21
+ content = {}
22
+
23
+ hash.each do |key, value|
24
+ if value.kind_of? String
25
+ new_value = interpolate_system_variable value
26
+
27
+ content[key] = new_value if new_value
28
+ elsif value.kind_of? Hash
29
+ content[key] = interpolate_system_variables value
30
+ else
31
+ content[key] = value
32
+ end
33
+ end
34
+
35
+ content
36
+ end
37
+
38
+ def interpolate_system_variable value
39
+ new_value = value
40
+
41
+ while new_value.index('ENV[')
42
+ index1 = new_value.index("ENV[")
43
+ index2 = new_value.index("]")
44
+
45
+ name = new_value[index1+5..index2-2]
46
+
47
+ left = (index1 == 0) ? '' : new_value[0..index1-1]
48
+ right = new_value[index2+1..-1]
49
+
50
+ new_value = left + ENV[name] + right
51
+ end
52
+
53
+ new_value
54
+ end
55
+
56
+ def build_variables_table content
57
+ var_table = {}
58
+
59
+ content.each do |key, value|
60
+ build_variable(var_table, key, key, value)
61
+ end
62
+
63
+ var_table
64
+ end
65
+
66
+ def build_variable(var_table, compound_key, key, value)
67
+ if value.kind_of? String
68
+ var_table[key] = value
69
+ elsif value.kind_of? Hash
70
+ build_hash var_table, compound_key, value
71
+ end
72
+ end
73
+
74
+ def build_hash var_table, compound_key, hash
75
+ hash.each do |key, value|
76
+ new_compound_key = "#{compound_key}.#{key}"
77
+
78
+ if value.kind_of? Hash
79
+ build_variable(var_table, new_compound_key, key, value)
80
+ else
81
+ var_table[new_compound_key.to_sym] = value
82
+ end
83
+ end
84
+ end
85
+
86
+ def interpolate_variables content, env, errors
87
+ hash = {}
88
+
89
+ begin
90
+ substitutions = false
91
+
92
+ content.each do |key, value|
93
+ new_value = value
94
+ substitutions = false
95
+
96
+ if value.kind_of? String
97
+ if value.index(/\#\{/)
98
+ substitutions = true
99
+
100
+ new_value = value.gsub(/\#{/, '%{')
101
+
102
+ begin
103
+ new_value = StringIO.new(new_value).read % env
104
+ rescue KeyError => e
105
+ substitutions = false
106
+
107
+ errors << e.message
108
+ end
109
+ end
110
+ elsif value.kind_of? Hash
111
+ new_value = interpolate_variables value, env, errors
112
+ end
113
+
114
+ if hash[key] == new_value
115
+ substitutions = false
116
+ else
117
+ hash[key] = new_value
118
+ end
119
+ end
120
+ end while substitutions
121
+
122
+ hash
123
+ end
124
+
125
+ end
@@ -1,7 +1,10 @@
1
1
  require 'stringio'
2
+ require 'text_interpolator/hash_processor'
2
3
 
3
4
  class TextInterpolator
4
5
 
6
+ attr_reader :errors
7
+
5
8
  def interpolate object, env={}
6
9
  if object.kind_of? String
7
10
  interpolate_string object, env
@@ -33,59 +36,9 @@ class TextInterpolator
33
36
  end
34
37
 
35
38
  def interpolate_hash hash
36
- hash.each do |key, value|
37
- new_value = interpolate_env_vars value
38
-
39
- hash[key] = new_value if new_value
40
- end
41
-
42
- env = hash.reduce({}) do |result, value|
43
- result[value[0]] = value[1]
44
-
45
- result
46
- end
39
+ result, @errors = *HashProcessor.instance.process(hash)
47
40
 
48
- begin
49
- substitutions = false
50
-
51
- hash.each do |key, value|
52
- if value.kind_of? String
53
- if value.index(/\#\{/)
54
- substitutions = true
55
-
56
- value = value.gsub(/\#{/, '%{')
57
-
58
- hash[key] = StringIO.new(value).read % env
59
- end
60
- end
61
- end
62
- end while substitutions
63
-
64
- hash
65
- end
66
-
67
- private
68
-
69
- def interpolate_env_vars value
70
- if value.kind_of? String
71
- while value.index('ENV[')
72
- value = interpolate_env_var value
73
- end
74
- end
75
-
76
- value
77
- end
78
-
79
- def interpolate_env_var value
80
- index1 = value.index("ENV[")
81
- index2 = value.index("]")
82
-
83
- name = value[index1+5..index2-2]
84
-
85
- left = (index1 == 0) ? '' : value[0..index1-1]
86
- right = value[index2+1..-1]
87
-
88
- left + ENV[name] + right
41
+ result
89
42
  end
90
43
 
91
44
  end
@@ -1,3 +1,3 @@
1
1
  class TextInterpolator
2
- VERSION = "1.0.5"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,6 +1,5 @@
1
1
  require File.expand_path('spec_helper', File.dirname(__FILE__))
2
2
 
3
- require 'json'
4
3
  require 'text_interpolator'
5
4
 
6
5
  describe TextInterpolator do
@@ -52,21 +51,15 @@ describe TextInterpolator do
52
51
  end
53
52
 
54
53
  describe "#interpolate_hash" do
55
- it "interpolates hash" do
56
- config =
57
- '{' +
58
- '"user": "ENV[\'USER\']",' +
59
-
60
- '"oracle_base": "/usr/local/oracle",' +
61
- '"oracle_version": "11.2.0.4.0",'+
62
-
63
- '"src_dir": "#{user}/downloads",' +
64
- '"dest_dir": "#{oracle_base}/instantclient_11_2",' +
65
-
66
- '"basic_zip": "#{src_dir}/instantclient-basic-macos.x64-#{oracle_version}.zip"' +
67
- '}'
68
-
69
- hash = JSON.parse(config, :symbolize_names => true)
54
+ it "interpolates simple hash" do
55
+ hash = {
56
+ user: ENV['USER'],
57
+ oracle_base: '/usr/local/oracle',
58
+ oracle_version: '11.2.0.4.0',
59
+ src_dir: '#{user}/downloads',
60
+ dest_dir: '#{oracle_base}/instantclient_11_2',
61
+ basic_zip: '#{src_dir}/instantclient-basic-macos.x64-#{oracle_version}.zip'
62
+ }
70
63
 
71
64
  result = subject.interpolate_hash hash
72
65
 
@@ -75,5 +68,39 @@ describe TextInterpolator do
75
68
  expect(result[:dest_dir]).to eq '/usr/local/oracle/instantclient_11_2'
76
69
  expect(result[:basic_zip]).to eq ENV['USER'] + '/downloads/instantclient-basic-macos.x64-11.2.0.4.0.zip'
77
70
  end
71
+
72
+ it "interpolates multi-level hash" do
73
+ hash = {
74
+ host: 'localhost',
75
+ user: ENV['USER'],
76
+ home: ENV['HOME'],
77
+
78
+ credentials: {
79
+ user: "some_user",
80
+ password: "some_password",
81
+
82
+ settings: {
83
+ user: "some_user2"
84
+ }
85
+ },
86
+
87
+ postgres: {
88
+ hostname: '#{host}',
89
+ user: '#{credentials.user}',
90
+ password: 'postgres'
91
+ },
92
+
93
+ mysql: {
94
+ user: '#{credentials.settings.user}',
95
+ }
96
+ }
97
+
98
+ result = subject.interpolate_hash hash
99
+
100
+ expect(result[:postgres][:user]).to eq hash[:credentials][:user]
101
+ expect(result[:mysql][:user]).to eq hash[:credentials][:settings][:user]
102
+
103
+ expect(subject.errors).to be_empty
104
+ end
78
105
  end
79
106
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: text-interpolator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Shvets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-03 00:00:00.000000000 Z
11
+ date: 2014-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gemspec_deps_gen
@@ -45,6 +45,7 @@ extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
47
  - .gitignore
48
+ - .idea/codeStyleSettings.xml
48
49
  - .ruby-gemset
49
50
  - .ruby-version
50
51
  - CHANGES
@@ -53,6 +54,7 @@ files:
53
54
  - README.md
54
55
  - Rakefile
55
56
  - lib/text_interpolator.rb
57
+ - lib/text_interpolator/hash_processor.rb
56
58
  - lib/text_interpolator/text_interpolator.rb
57
59
  - lib/text_interpolator/version.rb
58
60
  - spec/spec_helper.rb