constructorio 1.0.4 → 2.0.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,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a44d85b592d503fee64cbf411daf318ab52fcfc9
4
- data.tar.gz: 29aefce25803f2b066488c1550a047ee04ed0071
3
+ metadata.gz: 18db9093fcb9a5bd9ebcb0a13e74e0d828720695
4
+ data.tar.gz: cf0cf3d3c976f8face4928b86bb875c9174c9b64
5
5
  SHA512:
6
- metadata.gz: 736e434f3feae53f9c501764871c7a96529efc39fdd124f557dd8fc55db98fe44cb25f6e03d31222497cb47d78739ce0173d6b861dd74683731c4b9e285f2898
7
- data.tar.gz: 84df4cf7349f73b33f54cd0aa60f14a4f15b72d45630f442f1be4777550abb7b49a40fee1075abc5e41e2c84a6c1c821753b4ca9e801139bf06885045299abd0
6
+ metadata.gz: e7dde5ef1ee84ce2321d9caa2061e55b376ffdb425b4360c66f9b851b8d4bb49b357917fa53112a4f100a86acb19f42017391d783b63fdf6f30ebf6695ff3253
7
+ data.tar.gz: 005611dfe57cf1916995c0d8f16b00fbe1529d090b7bc371abd77f1df898120391421fe777eb0a71ba1aa72b366031cdc55c32d838dab732af18e775c722a206
data/.rock.yml CHANGED
@@ -6,5 +6,3 @@ env:
6
6
  build: |
7
7
  rm -f ./bin/bundle
8
8
  {{ parent }}
9
-
10
- run_web: bin/rails s
@@ -6,10 +6,10 @@ require 'constructorio/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "constructorio"
8
8
  spec.version = ConstructorIO::VERSION
9
- spec.authors = ["Steven Lai"]
10
- spec.email = ["lai.steven@gmail.com"]
9
+ spec.authors = ["Dan McCormick"]
10
+ spec.email = ["dan@constructor.io"]
11
11
  spec.summary = %q{Ruby gem for Constructor.io}
12
- spec.description = %q{Ruby gem for Constructor.io's autocomplete service. Enables Rails models to send updates to the Constructor.io API automatically, and provides a view helper to add autocomplete on any input.}
12
+ spec.description = %q{Ruby gem for Constructor.io's autocomplete service.}
13
13
  spec.homepage = "http://constructor.io"
14
14
  spec.license = "MIT"
15
15
 
@@ -18,13 +18,10 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "activerecord"
22
21
  spec.add_dependency 'faraday', '~> 0.9', '>= 0.9.0'
23
- spec.add_dependency "activesupport", ">= 3.2"
24
22
  spec.add_development_dependency "bundler", "~> 1.7"
25
23
  spec.add_development_dependency "rake", "~> 10.0"
26
24
  spec.add_development_dependency 'pry', '~> 0.10', '>= 0.10.1'
27
- spec.add_development_dependency 'sqlite3', '~> 1.3', '>= 1.3.10'
28
25
  spec.add_development_dependency 'mocha', '~> 1.1', '>= 1.1.0'
29
- spec.add_development_dependency "minitest", "~> 5.5.1"
26
+ spec.add_development_dependency 'minitest', '~> 5.5', '>= 5.5.1'
30
27
  end
@@ -0,0 +1,58 @@
1
+ require 'json'
2
+
3
+ module ConstructorIO
4
+ class Client
5
+ def add(params)
6
+ call_api("item", "post", params)
7
+ end
8
+
9
+ def remove(params)
10
+ call_api("item", "delete", params)
11
+ end
12
+
13
+ def modify(params)
14
+ call_api("item", "put", params)
15
+ end
16
+
17
+ def track_search(params)
18
+ call_api("search", "post", params)
19
+ end
20
+
21
+ def track_click_through(params)
22
+ call_api("click_through", "post", params)
23
+ end
24
+
25
+ def track_conversion(params)
26
+ call_api("conversion", "post", params)
27
+ end
28
+
29
+ def verify
30
+ call_api("verify", "get")
31
+ end
32
+
33
+ private
34
+
35
+ def call_api(path, method, params)
36
+ api_token = ConstructorIO.configuration.api_token
37
+ api_url = ConstructorIO.configuration.api_url || "https://ac.constructor.io/"
38
+ autocomplete_key = ConstructorIO.configuration.autocomplete_key
39
+ @http_client ||= Faraday.new(url: api_url)
40
+ @http_client.basic_auth(api_token, '')
41
+
42
+ send_request(path, method, @http_client, params, autocomplete_key)
43
+ end
44
+
45
+ def send_request(path, method, http_client, params, autocomplete_key)
46
+ response = http_client.send(method) do |request|
47
+ request.url "/v1/#{path}?autocomplete_key=#{autocomplete_key}"
48
+ request.headers['Content-Type'] = 'application/json'
49
+ request.body = params.to_json
50
+ end
51
+ if response.status.to_s =~ /^2/
52
+ return nil
53
+ else
54
+ return response.status
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module ConstructorIO
2
- VERSION = "1.0.4"
2
+ VERSION = "2.0.0"
3
3
  end
data/lib/constructorio.rb CHANGED
@@ -1,25 +1,15 @@
1
1
  require 'constructorio/version'
2
2
  require 'constructorio/configuration'
3
- require 'constructorio/helper'
4
- require 'constructorio/fields'
5
- require 'active_record'
3
+ require 'constructorio/client'
6
4
  require 'faraday'
7
- require 'active_support/core_ext/string/output_safety'
8
-
9
- require 'constructorio/railtie' if defined?(Rails)
10
5
 
11
6
  begin
12
7
  require 'pry'
13
8
  rescue LoadError
14
9
  end
15
10
 
16
- class MissingItemName < StandardError; end
17
-
18
11
  module ConstructorIO
19
-
20
- class << self
21
- attr_accessor :configuration
22
- end
12
+ attr_accessor :configuration
23
13
 
24
14
  def self.configuration
25
15
  @configuration ||= Configuration.new
@@ -28,95 +18,4 @@ module ConstructorIO
28
18
  def self.configure
29
19
  yield(configuration)
30
20
  end
31
-
32
- # This injects the methods on the included hook
33
- def self.included base
34
- base.send :include, InstanceMethods
35
- base.extend ClassMethods
36
- end
37
-
38
- module ClassMethods
39
- # "fields" is expected to be an array of strings or an array of hashes, like:
40
- # "product_name", "description"
41
- # - or -
42
- # { 'attribute' => 'product_name', 'metadata' => { metadata_one => ->{ something_dynamic }} }
43
- def constructorio_autocomplete(fields, autocomplete_key = ConstructorIO.configuration.autocomplete_key)
44
- # All fields require an attribute
45
- field_names = fields.map { |f| f.is_a?(String) ? f : f['attribute'] }
46
- raise MissingItemName if field_names.include? nil
47
-
48
- field_names.each do |field|
49
- ConstructorIO::Fields.instance.add(self.model_name, field)
50
- end
51
-
52
- # transform the data
53
- transformed = {}
54
- fields.each do |field|
55
- if field.is_a?(String)
56
- transformed[field] = {}
57
- else
58
- transformed[field['attribute']] = field['metadata']
59
- end
60
- end
61
-
62
- after_save do |record|
63
- updated_fields = record.changed.select { |c| field_names.include? c }
64
- updated_fields.each do |field|
65
- record.send(:constructorio_add_record, record[field.to_sym], transformed[field], autocomplete_key)
66
- end
67
- end
68
-
69
- before_destroy do |record|
70
- field_names.each do |field|
71
- record.send(:constructorio_delete_record, record[field.to_sym], transformed[field], autocomplete_key)
72
- end
73
- end
74
- end
75
- end
76
-
77
- module InstanceMethods
78
- def constructorio_add_record(value, metadata = {}, autocomplete_key)
79
- constructorio_call_api("post", value, metadata, autocomplete_key)
80
- end
81
-
82
- def constructorio_delete_record(value, metadata = {}, autocomplete_key)
83
- constructorio_call_api("delete", value, metadata, autocomplete_key)
84
- end
85
-
86
- private
87
-
88
- def constructorio_make_request_body(value, metadata)
89
- request_body = { "item_name" => "#{value}" }
90
- unless metadata.empty?
91
- metadata.each do |k, v|
92
- v = instance_exec(&v) if v.is_a? Proc
93
- request_body[k] = v
94
- end
95
- end
96
- request_body
97
- end
98
-
99
- def constructorio_call_api(method, value, metadata, autocomplete_key)
100
- api_token = ConstructorIO.configuration.api_token
101
- api_url = ConstructorIO.configuration.api_url || "https://ac.constructor.io/"
102
- @http_client ||= Faraday.new(url: api_url)
103
- @http_client.basic_auth(api_token, '')
104
-
105
- request_body = constructorio_make_request_body(value, metadata)
106
- constructorio_send_request(method, @http_client, request_body, autocomplete_key)
107
- end
108
-
109
- def constructorio_send_request(method, http_client, request_body, autocomplete_key)
110
- response = http_client.send(method) do |request|
111
- request.url "/v1/item?autocomplete_key=#{autocomplete_key}"
112
- request.headers['Content-Type'] = 'application/json'
113
- request.body = request_body.to_json
114
- end
115
- if response.status.to_s =~ /^2/
116
- return nil
117
- else
118
- return response.status
119
- end
120
- end
121
- end
122
21
  end
@@ -1,106 +1,50 @@
1
1
  require_relative 'test_helper'
2
2
 
3
3
  class ConstructorIOTest < MiniTest::Test
4
- def test_add_record_makes_request
5
- person = Person.new(
6
- first_name: "Steven",
7
- last_name: "Lai",
8
- address: "New York"
4
+ def test_add_record_calls_post
5
+ c = ConstructorIO::Client.new
6
+ c.expects(:call_api).with(
7
+ "item",
8
+ "post",
9
+ { item_name: "power drill" }
9
10
  )
10
11
 
11
- person.stubs(:constructorio_send_request)
12
-
13
- person.expects(:constructorio_make_request_body)
14
- assert person.save
15
- end
16
-
17
- def test_add_simple_record_makes_request
18
- person = PersonSimple.new(
19
- first_name: "Steven",
20
- last_name: "Lai",
21
- address: "New York"
22
- )
23
-
24
- person.stubs(:constructorio_send_request)
25
-
26
- person.expects(:constructorio_make_request_body)
27
- assert person.save
28
- end
29
-
30
- def test_add_record_accepts_procs
31
- person = Person.new(
32
- first_name: "Steven",
33
- last_name: "Lai",
34
- address: "New York"
35
- )
36
-
37
- person.expects(:constructorio_send_request).with(
38
- 'post',
39
- instance_of(Faraday::Connection),
40
- {'item_name' => 'Steven', 'test_metadata' => 'test_values', 'test_proc' => 'NEW YORK'},
41
- 'person_autocomplete_key'
42
- )
43
- assert person.save
44
- end
45
-
46
- def test_add_simple_record_accepts_procs
47
- person = PersonSimple.new(
48
- first_name: "Steven",
49
- last_name: "Lai",
50
- address: "New York"
51
- )
52
-
53
- person.expects(:constructorio_send_request).with(
54
- 'post',
55
- instance_of(Faraday::Connection),
56
- {'item_name' => 'Steven'},
57
- 'example_autocomplete_key'
58
- )
59
- assert person.save
12
+ c.add( { item_name: "power drill" } )
60
13
  end
61
14
 
62
15
  def test_add_record_sends_request
63
- person = Person.new(
64
- first_name: "Steven",
65
- last_name: "Lai",
66
- address: "New York"
16
+ c = ConstructorIO::Client.new
17
+ c.expects(:send_request).with(
18
+ "item",
19
+ "post",
20
+ instance_of(Faraday::Connection),
21
+ { item_name: "power drill" },
22
+ "example_autocomplete_key"
67
23
  )
68
24
 
69
- person.expects(:constructorio_send_request)
70
- assert person.save
25
+ c.add( { item_name: "power drill" } )
71
26
  end
72
27
 
73
- def test_delete_record_makes_request
74
- Person.any_instance.stubs(:constructorio_call_api)
75
- person = Person.create(
76
- first_name: "Ronald",
77
- last_name: "McDonald",
78
- address: "Disneyland"
28
+ def test_remove_record_calls_delete
29
+ c = ConstructorIO::Client.new
30
+ c.expects(:call_api).with(
31
+ "item",
32
+ "delete",
33
+ { item_name: "power drill" }
79
34
  )
80
35
 
81
- person.expects(:constructorio_call_api).with("delete", "Ronald", has_entry('test_proc', instance_of(Proc)),"person_autocomplete_key")
82
- person.destroy
36
+ c.remove( { item_name: "power drill" } )
83
37
  end
84
38
 
85
- def test_add_record_without_key_uses_default_key
86
- person = PersonNoKey.new(
87
- first_name: "Steven",
88
- last_name: "Lai",
89
- address: "New York"
39
+ def test_modify_record_calls_put
40
+ c = ConstructorIO::Client.new
41
+ c.expects(:call_api).with(
42
+ "item",
43
+ "put",
44
+ { item_name: "power drill" }
90
45
  )
91
46
 
92
- person.expects(:constructorio_call_api).with("post", "Lai", anything, ConstructorIO.configuration.autocomplete_key)
93
- assert person.save
47
+ c.modify( { item_name: "power drill" } )
94
48
  end
95
49
 
96
- def test_fields_are_tracked
97
- Person.any_instance.expects(:constructorio_call_api).with("post", "Ronald", anything, "person_autocomplete_key")
98
- person = Person.create(
99
- first_name: "Ronald",
100
- last_name: "McDonald",
101
- address: "Disneyland"
102
- )
103
-
104
- assert_equal ConstructorIO::Fields.instance.list('Person'), ["first_name"]
105
- end
106
50
  end
data/test/test_helper.rb CHANGED
@@ -3,49 +3,8 @@ require 'minitest/unit'
3
3
  require 'mocha/mini_test'
4
4
  require_relative '../lib/constructorio'
5
5
 
6
-
7
- ActiveRecord::Base.establish_connection(
8
- adapter: 'sqlite3',
9
- database: ':memory:'
10
- )
11
-
12
- ActiveRecord::Schema.define do
13
- create_table :people, force: true do |t|
14
- t.string :first_name
15
- t.string :last_name
16
- t.string :address
17
- end
18
- end
19
-
20
6
  ConstructorIO.configure do |config|
21
7
  config.api_token = "example_api_token"
22
8
  config.autocomplete_key = "example_autocomplete_key"
23
9
  config.api_url = "http://example.constructor.io"
24
10
  end
25
-
26
- class Person < ActiveRecord::Base
27
- include ConstructorIO
28
- constructorio_autocomplete [{
29
- 'attribute' => 'first_name',
30
- 'metadata' => {
31
- 'test_metadata' => 'test_values',
32
- 'test_proc' => ->{ self.address.upcase }
33
- }
34
- }], "person_autocomplete_key"
35
- end
36
-
37
- class PersonSimple < ActiveRecord::Base
38
- self.table_name = 'people'
39
- include ConstructorIO
40
- constructorio_autocomplete [ 'first_name' ]
41
- end
42
-
43
- class PersonNoKey < ActiveRecord::Base
44
- self.table_name = 'people'
45
- include ConstructorIO
46
- constructorio_autocomplete [{'attribute' => 'last_name'}]
47
- end
48
-
49
- class FakeView
50
- include ConstructorIO::Helper
51
- end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: constructorio
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.4
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
- - Steven Lai
7
+ - Dan McCormick
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-16 00:00:00.000000000 Z
11
+ date: 2015-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: activerecord
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: faraday
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -44,20 +30,6 @@ dependencies:
44
30
  - - ">="
45
31
  - !ruby/object:Gem::Version
46
32
  version: 0.9.0
47
- - !ruby/object:Gem::Dependency
48
- name: activesupport
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '3.2'
54
- type: :runtime
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- version: '3.2'
61
33
  - !ruby/object:Gem::Dependency
62
34
  name: bundler
63
35
  requirement: !ruby/object:Gem::Requirement
@@ -106,26 +78,6 @@ dependencies:
106
78
  - - ">="
107
79
  - !ruby/object:Gem::Version
108
80
  version: 0.10.1
109
- - !ruby/object:Gem::Dependency
110
- name: sqlite3
111
- requirement: !ruby/object:Gem::Requirement
112
- requirements:
113
- - - "~>"
114
- - !ruby/object:Gem::Version
115
- version: '1.3'
116
- - - ">="
117
- - !ruby/object:Gem::Version
118
- version: 1.3.10
119
- type: :development
120
- prerelease: false
121
- version_requirements: !ruby/object:Gem::Requirement
122
- requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: '1.3'
126
- - - ">="
127
- - !ruby/object:Gem::Version
128
- version: 1.3.10
129
81
  - !ruby/object:Gem::Dependency
130
82
  name: mocha
131
83
  requirement: !ruby/object:Gem::Requirement
@@ -151,6 +103,9 @@ dependencies:
151
103
  requirement: !ruby/object:Gem::Requirement
152
104
  requirements:
153
105
  - - "~>"
106
+ - !ruby/object:Gem::Version
107
+ version: '5.5'
108
+ - - ">="
154
109
  - !ruby/object:Gem::Version
155
110
  version: 5.5.1
156
111
  type: :development
@@ -158,13 +113,14 @@ dependencies:
158
113
  version_requirements: !ruby/object:Gem::Requirement
159
114
  requirements:
160
115
  - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '5.5'
118
+ - - ">="
161
119
  - !ruby/object:Gem::Version
162
120
  version: 5.5.1
163
- description: Ruby gem for Constructor.io's autocomplete service. Enables Rails models
164
- to send updates to the Constructor.io API automatically, and provides a view helper
165
- to add autocomplete on any input.
121
+ description: Ruby gem for Constructor.io's autocomplete service.
166
122
  email:
167
- - lai.steven@gmail.com
123
+ - dan@constructor.io
168
124
  executables: []
169
125
  extensions: []
170
126
  extra_rdoc_files: []
@@ -178,16 +134,12 @@ files:
178
134
  - Rakefile
179
135
  - constructorio.gemspec
180
136
  - lib/constructorio.rb
137
+ - lib/constructorio/client.rb
181
138
  - lib/constructorio/configuration.rb
182
- - lib/constructorio/fields.rb
183
- - lib/constructorio/helper.rb
184
- - lib/constructorio/railtie.rb
185
- - lib/constructorio/tasks/import.rake
186
139
  - lib/constructorio/version.rb
187
140
  - test/configuration_test.rb
188
141
  - test/constructorio_test.rb
189
142
  - test/test_helper.rb
190
- - test/view_helper_test.rb
191
143
  homepage: http://constructor.io
192
144
  licenses:
193
145
  - MIT
@@ -216,4 +168,3 @@ test_files:
216
168
  - test/configuration_test.rb
217
169
  - test/constructorio_test.rb
218
170
  - test/test_helper.rb
219
- - test/view_helper_test.rb
@@ -1,27 +0,0 @@
1
- require 'singleton'
2
-
3
- module ConstructorIO
4
- class Fields
5
- include Singleton
6
-
7
- attr_accessor :set
8
-
9
- def initialize
10
- @set = {}
11
- end
12
-
13
- def add(model_name, field)
14
- @set[model_name] ||= {}
15
- @set[model_name][field] = 1
16
- end
17
-
18
- def list(model_name)
19
- if @set[model_name].is_a?(Hash)
20
- @set[model_name].keys
21
- else
22
- []
23
- end
24
- end
25
- end
26
- end
27
-
@@ -1,11 +0,0 @@
1
- # usage: <%= autocomplete :dom_id => "search" %>
2
-
3
- module ConstructorIO
4
- module Helper
5
- def constructorio_autocomplete(options = {})
6
- result = %Q|<script type="text/javascript" src="//cnstrc.com/js/ac.js"></script>\n|
7
- result += %Q|<script>$(document).ready(function(){ $('##{options[:dom_id]}').constructorAutocomplete({ key: '#{ConstructorIO.configuration.autocomplete_key}' }); })</script>|
8
- return result.html_safe
9
- end
10
- end
11
- end
@@ -1,15 +0,0 @@
1
- require 'rails'
2
-
3
- module ConstructorIO
4
- class Railtie < Rails::Railtie
5
- initializer 'constructorio.action_view' do
6
- ActiveSupport.on_load(:action_view) do
7
- include ConstructorIO::Helper
8
- end
9
- end
10
-
11
- rake_tasks do
12
- Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
13
- end
14
- end
15
- end
@@ -1,25 +0,0 @@
1
- namespace :constructorio do
2
- import_model_desc = <<-DESC.gsub(/ /, '')
3
- Import data from your model (pass name as CLASS environment variable).
4
-
5
- $ rake environment constructorio:import:model CLASS='MyModel'
6
- DESC
7
-
8
- task :import => 'import:model'
9
-
10
- namespace :import do
11
- desc import_model_desc
12
-
13
- task :model do
14
- klass = eval(ENV['CLASS'].to_s)
15
- fields = ConstructorIO::Fields.instance.list(klass.model_name)
16
- if fields.any?
17
- klass.all.each do |record|
18
- fields.each do |field|
19
- klass.add_record(record[field.to_sym], ConstructorIO.configuration.autocomplete_key)
20
- end
21
- end
22
- end
23
- end
24
- end
25
- end
@@ -1,11 +0,0 @@
1
- require_relative 'test_helper'
2
-
3
- class ViewHelperTest < MiniTest::Test
4
- def setup
5
- @fakeview = FakeView.new
6
- end
7
-
8
- def test_autocomplete_html
9
- assert_equal @fakeview.constructorio_autocomplete(dom_id: 'a'), "<script type=\"text/javascript\" src=\"//cnstrc.com/js/ac.js\"></script>\n<script>$(document).ready(function(){ $('#a').constructorAutocomplete({ key: 'example_autocomplete_key' }); })</script>"
10
- end
11
- end