talkable 0.0.0 → 0.9.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.
Files changed (38) hide show
  1. checksums.yaml +13 -5
  2. data/.gitignore +4 -2
  3. data/.rspec +1 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +126 -0
  6. data/LICENSE +22 -0
  7. data/README.md +144 -185
  8. data/Rakefile +17 -0
  9. data/lib/talkable.rb +43 -0
  10. data/lib/talkable/api.rb +13 -0
  11. data/lib/talkable/api/base.rb +98 -0
  12. data/lib/talkable/api/offer.rb +11 -0
  13. data/lib/talkable/api/origin.rb +29 -0
  14. data/lib/talkable/api/person.rb +17 -0
  15. data/lib/talkable/api/referral.rb +19 -0
  16. data/lib/talkable/api/reward.rb +19 -0
  17. data/lib/talkable/api/share.rb +19 -0
  18. data/lib/talkable/api/visitor.rb +13 -0
  19. data/lib/talkable/configuration.rb +40 -0
  20. data/lib/talkable/generators/install_generator.rb +81 -0
  21. data/lib/talkable/generators/templates/app/controllers/invite_controller.rb +8 -0
  22. data/lib/talkable/generators/templates/app/views/invite/show.html.erb +2 -0
  23. data/lib/talkable/generators/templates/app/views/invite/show.html.haml +2 -0
  24. data/lib/talkable/generators/templates/app/views/invite/show.html.slim +2 -0
  25. data/lib/talkable/generators/templates/app/views/shared/_talkable_offer.html.erb +4 -0
  26. data/lib/talkable/generators/templates/app/views/shared/_talkable_offer.html.haml +3 -0
  27. data/lib/talkable/generators/templates/app/views/shared/_talkable_offer.html.slim +3 -0
  28. data/lib/talkable/generators/templates/config/initializers/talkable.rb +13 -0
  29. data/lib/talkable/integration.rb +41 -0
  30. data/lib/talkable/middleware.rb +147 -0
  31. data/lib/talkable/railtie.rb +11 -0
  32. data/lib/talkable/resources.rb +3 -0
  33. data/lib/talkable/resources/offer.rb +49 -0
  34. data/lib/talkable/resources/origin.rb +22 -0
  35. data/lib/talkable/version.rb +3 -0
  36. data/solano.yml +20 -0
  37. data/talkable.gemspec +37 -0
  38. metadata +202 -9
@@ -0,0 +1,2 @@
1
+ <div id="talkable-inline-offer-container"></div>
2
+ <%= render 'shared/talkable_offer', offer: @invite_offer, options: {iframe: {container: 'talkable-inline-offer-container'}} %>
@@ -0,0 +1,2 @@
1
+ #talkable-inline-offer-container
2
+ = render 'shared/talkable_offer', offer: @invite_offer, options: {iframe: {container: 'talkable-inline-offer-container'}}
@@ -0,0 +1,2 @@
1
+ #talkable-inline-offer-container
2
+ = render 'shared/talkable_offer', offer: @invite_offer, options: {iframe: {container: 'talkable-inline-offer-container'}}
@@ -0,0 +1,4 @@
1
+ <%- options ||= {} %>
2
+ <%- if offer %>
3
+ <%== offer.advocate_share_iframe(options) %>
4
+ <% end -%>
@@ -0,0 +1,3 @@
1
+ - options ||= {}
2
+ - if offer
3
+ != offer.advocate_share_iframe(options)
@@ -0,0 +1,3 @@
1
+ - options ||= {}
2
+ - if offer
3
+ == offer.advocate_share_iframe(options)
@@ -0,0 +1,13 @@
1
+ Talkable.configure do |config|
2
+ # site slug is taken takes form ENV["TALKABLE_SITE_SLUG"]
3
+ config.site_slug = <%= @site_slug.inspect %>
4
+
5
+ # api key is taken from ENV["TALKABLE_API_KEY"]
6
+ config.api_key = <%= @api_key.inspect %>
7
+ <%- if defined?(@server) && @server.present? %>
8
+ config.server = <%= @server.inspect %>
9
+ <%- else %>
10
+ # custom server address - by default <%= Talkable::Configuration::DEFAULT_SERVER %>
11
+ # config.server =
12
+ <%- end %>
13
+ end
@@ -0,0 +1,41 @@
1
+ module Talkable
2
+ DEFAULT_CAMPAIGN_TAGS = {
3
+ Talkable::API::Origin::AFFILIATE_MEMBER => 'invite'.freeze,
4
+ Talkable::API::Origin::PURCHASE => 'post-purchase'.freeze,
5
+ Talkable::API::Origin::EVENT => nil,
6
+ }.freeze
7
+
8
+ class << self
9
+ def register_affiliate_member(params)
10
+ register_origin(Talkable::API::Origin::AFFILIATE_MEMBER, params)
11
+ end
12
+
13
+ def register_purchase(params)
14
+ register_origin(Talkable::API::Origin::PURCHASE, params)
15
+ end
16
+
17
+ def register_event(params)
18
+ register_origin(Talkable::API::Origin::EVENT, params)
19
+ end
20
+
21
+ private
22
+
23
+ def register_origin(origin_type, params)
24
+ origin_params = default_params(origin_type).merge(params)
25
+ result = Talkable::API::Origin.create(origin_type, origin_params)
26
+ origin = Talkable::Origin.parse(result)
27
+ if offer = origin.offer
28
+ # make sure that explicitly specified tags will be listed first
29
+ tags = Array(origin_params[:campaign_tags]) | Array(offer.campaign_tags)
30
+ offer.campaign_tags = tags.map(&:to_s).uniq
31
+ end
32
+ origin
33
+ end
34
+
35
+ def default_params(origin_type)
36
+ {
37
+ campaign_tags: DEFAULT_CAMPAIGN_TAGS[origin_type]
38
+ }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,147 @@
1
+ require 'cgi'
2
+ require 'rack/request'
3
+
4
+ module Talkable
5
+ class Middleware
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ uuid = talkable_visitor_uuid(env)
12
+
13
+ result = Talkable.with_uuid(uuid) do
14
+ @app.call(env)
15
+ end
16
+
17
+ inject_uuid_in_cookie(uuid, result)
18
+ modify_response_content(result) do |content|
19
+ content = inject_uuid_in_body(uuid, content)
20
+ inject_integration_js_in_head(content)
21
+ end
22
+
23
+ end
24
+
25
+ protected
26
+
27
+ def talkable_visitor_uuid(env)
28
+ req = Rack::Request.new(env)
29
+ req.params[UUID] || req.cookies[UUID] || Talkable.find_or_generate_uuid
30
+ end
31
+
32
+ def inject_uuid_in_cookie(uuid, result)
33
+ Rack::Utils.set_cookie_header!(result[1], UUID, {value: uuid, path: '/', expires: cookies_expiration})
34
+ end
35
+
36
+ def modify_response_content(result)
37
+ return result unless modifiable?(result)
38
+
39
+ status, header, body = result
40
+ response_content = collect_content(body)
41
+ body.close if body.respond_to?(:close)
42
+
43
+ response_content = yield(response_content) if block_given?
44
+
45
+ if response_content
46
+ response = Rack::Response.new(response_content, status, header)
47
+ response.finish
48
+ else
49
+ result
50
+ end
51
+ end
52
+
53
+ def inject_uuid_in_body(uuid, content)
54
+ if injection_index = body_injection_position(content)
55
+ content = inject_in_content(content, sync_uuid_content(uuid), injection_index)
56
+ end
57
+ content
58
+ end
59
+
60
+ def inject_integration_js_in_head(content)
61
+ if injection_index = head_injection_position(content)
62
+ content = inject_in_content(content, integration_content, injection_index)
63
+ end
64
+ content
65
+ end
66
+
67
+ def inject_in_content(content, injection, position)
68
+ content[0...position] << injection << content[position..-1]
69
+ end
70
+
71
+ def cookies_expiration
72
+ Time.now + (20 * 365 * 24 * 60 * 60) # 20 years
73
+ end
74
+
75
+ def sync_uuid_url(uuid)
76
+ Furi.update("https://www.talkable.com/public/1x1.gif", query: {current_visitor_uuid: uuid})
77
+ end
78
+
79
+ def sync_uuid_content(uuid)
80
+ src = CGI.escape_html(sync_uuid_url(uuid))
81
+ %Q{
82
+ <img src="#{src}" style="position:absolute; left:-9999px;" alt="" />
83
+ }
84
+ end
85
+
86
+ def integration_content
87
+ integration_init_content + integration_script_content
88
+ end
89
+
90
+ def integration_init_content
91
+ %Q{
92
+ <script>
93
+ window._talkableq = window._talkableq || [];
94
+ _talkableq.push(['init', #{init_parameters.to_json}]);
95
+ </script>
96
+ }
97
+ end
98
+
99
+ def init_parameters
100
+ {
101
+ site_id: Talkable.configuration.site_slug,
102
+ server: Talkable.configuration.server,
103
+ }
104
+ end
105
+
106
+ def integration_script_content
107
+ src = CGI.escape_html(Talkable.configuration.js_integration_library)
108
+ %Q{
109
+ <script src="#{src}" type="text/javascript"></script>
110
+ }
111
+ end
112
+
113
+ def modifiable?(result)
114
+ status, headers = result
115
+ status == 200 && html?(headers) && !attachment?(headers)
116
+ end
117
+
118
+ def collect_content(chunks)
119
+ ''.tap do |content|
120
+ chunks.each { |chunk| content << chunk.to_s }
121
+ end
122
+ end
123
+
124
+ def body_injection_position(content)
125
+ pattern = /<\s*body[^>]*>/im
126
+ match = pattern.match(content)
127
+ match.end(0) if match
128
+ end
129
+
130
+ def head_injection_position(content)
131
+ pattern = /<\s*\/\s*head[^>]*>/im
132
+ match = pattern.match(content)
133
+ match.begin(0) if match
134
+ end
135
+
136
+ def html?(headers)
137
+ content_type = headers['Content-Type']
138
+ content_type && content_type.include?('text/html')
139
+ end
140
+
141
+ def attachment?(headers)
142
+ content_disposition = headers['Content-Disposition']
143
+ content_disposition && content_disposition.include?('attachment')
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,11 @@
1
+ module Talkable
2
+ class Railtie < Rails::Railtie
3
+ generators do
4
+ require 'talkable/generators/install_generator'
5
+ end
6
+
7
+ initializer "talkable.add_middleware" do |app|
8
+ app.middleware.use Talkable::Middleware
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ require 'hashie'
2
+ require 'talkable/resources/origin'
3
+ require 'talkable/resources/offer'
@@ -0,0 +1,49 @@
1
+ module Talkable
2
+ class Offer < Hashie::Mash
3
+ def self.parse(result_hash)
4
+ offer = self.new(result_hash[:offer])
5
+ offer.claim_links ||= Hashie::Mash.new(result_hash[:claim_links])
6
+ offer
7
+ end
8
+
9
+ def advocate_share_iframe(options = {})
10
+ show_trigger = !options[:ignore_trigger]
11
+ tag = campaign_tags.first
12
+ iframe_options = default_iframe_options(tag).merge(options[:iframe] || {})
13
+ url = show_trigger ? Furi.merge(show_url, query: {trigger_enabled: 1}) : show_url
14
+
15
+ snippets = []
16
+ if !options[:iframe] || !options[:iframe][:container]
17
+ snippets << render_container_snipet(iframe_options[:container])
18
+ end
19
+ snippets << render_share_snipet({
20
+ url: url,
21
+ iframe: iframe_options,
22
+ })
23
+
24
+ snippets.join("\n")
25
+ end
26
+
27
+ protected
28
+
29
+ def default_iframe_options(tag = nil)
30
+ tag ||= SecureRandom.hex(3)
31
+ {
32
+ container: "talkable-offer-#{tag}",
33
+ }
34
+ end
35
+
36
+ def render_container_snipet(name)
37
+ "<div id='#{CGI.escape(name)}'></div>"
38
+ end
39
+
40
+ def render_share_snipet(show_options)
41
+ %Q{
42
+ <script>
43
+ _talkableq.push(['show_offer', #{show_options.to_json}])
44
+ </script>
45
+ }
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,22 @@
1
+ require 'time'
2
+
3
+ module Talkable
4
+ class Origin < Hashie::Mash
5
+ def self.parse(result_hash)
6
+ origin_hash = result_hash[:origin]
7
+ order_date = (origin_hash ? origin_hash[:order_date] : nil)
8
+
9
+ if order_date
10
+ origin_hash[:order_date] = begin
11
+ Time.iso8601(order_date)
12
+ rescue ArgumentError
13
+ order_date
14
+ end
15
+ end
16
+
17
+ origin = self.new(origin_hash)
18
+ origin.offer ||= Talkable::Offer.parse(result_hash)
19
+ origin
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Talkable
2
+ VERSION = "0.9.0".freeze
3
+ end
data/solano.yml ADDED
@@ -0,0 +1,20 @@
1
+ ---
2
+ timeout: 900
3
+ timeout_hook: 900
4
+ bundler_version: 1.12.5
5
+ ruby_version:
6
+ SPLIT:
7
+ - "1.9.3"
8
+ - "2.0.0"
9
+ - "2.1.0"
10
+ - "2.2.0"
11
+ - "2.3.0"
12
+ test_pattern:
13
+ - spec/**_spec.rb
14
+ hooks:
15
+ pre_setup: bundle install
16
+ cache:
17
+ nocache: true
18
+ coverage:
19
+ version: 2
20
+ enabled: true
data/talkable.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+ require 'talkable/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "talkable"
6
+ s.version = Talkable::VERSION
7
+ s.date = Date.today.to_s
8
+ s.summary = "Talkable Referral Programe API"
9
+ s.description = "Talkable Ruby Gem to make your own referral program in Sinatra or Rails application"
10
+ s.authors = ["Talkable"]
11
+ s.email = "dev@talkable.com"
12
+ s.homepage = "https://github.com/talkable/talkable-ruby"
13
+ s.license = 'MIT'
14
+
15
+ s.files = `git ls-files`.split("\n").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.required_ruby_version = ">= 1.9.3"
19
+
20
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.2.2')
21
+ s.add_dependency "rack", ">= 1.5.2", "< 2"
22
+ else
23
+ s.add_dependency "rack", ">= 1.5.2"
24
+ end
25
+
26
+ s.add_dependency "furi", "~> 0.2"
27
+ s.add_dependency "hashie", "~> 3.4"
28
+
29
+ s.add_development_dependency "bundler", "~> 1.12"
30
+ s.add_development_dependency "rake", "~> 11.2"
31
+ s.add_development_dependency "rspec", "~> 3.4"
32
+ s.add_development_dependency "simplecov", "~> 0.12"
33
+ s.add_development_dependency "json", "~> 1.8.3" if RUBY_VERSION < '2.0'
34
+ s.add_development_dependency "webmock", "~> 2.1"
35
+ s.add_development_dependency "ammeter" # specs for generators
36
+ s.add_development_dependency "haml" # check haml syntex in generators
37
+ end
metadata CHANGED
@@ -1,15 +1,175 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: talkable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Talkable
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-11 00:00:00.000000000 Z
12
- dependencies: []
11
+ date: 2016-10-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.5.2
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 1.5.2
30
+ - - <
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
33
+ - !ruby/object:Gem::Dependency
34
+ name: furi
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ version: '0.2'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '0.2'
47
+ - !ruby/object:Gem::Dependency
48
+ name: hashie
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.4'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ version: '3.4'
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ~>
66
+ - !ruby/object:Gem::Version
67
+ version: '1.12'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: '1.12'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ~>
80
+ - !ruby/object:Gem::Version
81
+ version: '11.2'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ~>
87
+ - !ruby/object:Gem::Version
88
+ version: '11.2'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ~>
94
+ - !ruby/object:Gem::Version
95
+ version: '3.4'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ~>
101
+ - !ruby/object:Gem::Version
102
+ version: '3.4'
103
+ - !ruby/object:Gem::Dependency
104
+ name: simplecov
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '0.12'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ~>
115
+ - !ruby/object:Gem::Version
116
+ version: '0.12'
117
+ - !ruby/object:Gem::Dependency
118
+ name: json
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ~>
122
+ - !ruby/object:Gem::Version
123
+ version: 1.8.3
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ~>
129
+ - !ruby/object:Gem::Version
130
+ version: 1.8.3
131
+ - !ruby/object:Gem::Dependency
132
+ name: webmock
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ~>
136
+ - !ruby/object:Gem::Version
137
+ version: '2.1'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ~>
143
+ - !ruby/object:Gem::Version
144
+ version: '2.1'
145
+ - !ruby/object:Gem::Dependency
146
+ name: ammeter
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ! '>='
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ - !ruby/object:Gem::Dependency
160
+ name: haml
161
+ requirement: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ! '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
13
173
  description: Talkable Ruby Gem to make your own referral program in Sinatra or Rails
14
174
  application
15
175
  email: dev@talkable.com
@@ -17,8 +177,42 @@ executables: []
17
177
  extensions: []
18
178
  extra_rdoc_files: []
19
179
  files:
20
- - ".gitignore"
180
+ - .gitignore
181
+ - .rspec
182
+ - Gemfile
183
+ - Gemfile.lock
184
+ - LICENSE
21
185
  - README.md
186
+ - Rakefile
187
+ - lib/talkable.rb
188
+ - lib/talkable/api.rb
189
+ - lib/talkable/api/base.rb
190
+ - lib/talkable/api/offer.rb
191
+ - lib/talkable/api/origin.rb
192
+ - lib/talkable/api/person.rb
193
+ - lib/talkable/api/referral.rb
194
+ - lib/talkable/api/reward.rb
195
+ - lib/talkable/api/share.rb
196
+ - lib/talkable/api/visitor.rb
197
+ - lib/talkable/configuration.rb
198
+ - lib/talkable/generators/install_generator.rb
199
+ - lib/talkable/generators/templates/app/controllers/invite_controller.rb
200
+ - lib/talkable/generators/templates/app/views/invite/show.html.erb
201
+ - lib/talkable/generators/templates/app/views/invite/show.html.haml
202
+ - lib/talkable/generators/templates/app/views/invite/show.html.slim
203
+ - lib/talkable/generators/templates/app/views/shared/_talkable_offer.html.erb
204
+ - lib/talkable/generators/templates/app/views/shared/_talkable_offer.html.haml
205
+ - lib/talkable/generators/templates/app/views/shared/_talkable_offer.html.slim
206
+ - lib/talkable/generators/templates/config/initializers/talkable.rb
207
+ - lib/talkable/integration.rb
208
+ - lib/talkable/middleware.rb
209
+ - lib/talkable/railtie.rb
210
+ - lib/talkable/resources.rb
211
+ - lib/talkable/resources/offer.rb
212
+ - lib/talkable/resources/origin.rb
213
+ - lib/talkable/version.rb
214
+ - solano.yml
215
+ - talkable.gemspec
22
216
  homepage: https://github.com/talkable/talkable-ruby
23
217
  licenses:
24
218
  - MIT
@@ -29,19 +223,18 @@ require_paths:
29
223
  - lib
30
224
  required_ruby_version: !ruby/object:Gem::Requirement
31
225
  requirements:
32
- - - ">="
226
+ - - ! '>='
33
227
  - !ruby/object:Gem::Version
34
- version: '0'
228
+ version: 1.9.3
35
229
  required_rubygems_version: !ruby/object:Gem::Requirement
36
230
  requirements:
37
- - - ">="
231
+ - - ! '>='
38
232
  - !ruby/object:Gem::Version
39
233
  version: '0'
40
234
  requirements: []
41
235
  rubyforge_project:
42
- rubygems_version: 2.4.7
236
+ rubygems_version: 2.4.8
43
237
  signing_key:
44
238
  specification_version: 4
45
239
  summary: Talkable Referral Programe API
46
240
  test_files: []
47
- has_rdoc: