constructorio 1.0.2 → 1.0.3
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 +4 -4
- data/README.md +1 -1
- data/lib/constructorio.rb +79 -32
- data/lib/constructorio/fields.rb +3 -3
- data/lib/constructorio/version.rb +1 -1
- data/test/constructorio_test.rb +68 -10
- data/test/test_helper.rb +15 -6
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0afa62571df5734cb0bec7f26976b1ff8b4ed039
|
4
|
+
data.tar.gz: 8bfbffbaee6ff520ec59a6d5208ef3fd5dba5b7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 479bdfc0a8a29dfbcb15254af5f36a88438db4763f53d5ccbaa3a67cd5af066ac9f673483b154e36e788b9f47daa4f3e093b36a4dece7e899dd0581804f9db8b
|
7
|
+
data.tar.gz: cfeca1527e5c9f1d543e38a514e41e02310c5a181d9e11c29effcbd288d1a68fb8c2a85468317ebf7efe2fcb8778927518c3a99fb893069b600fd3e8d5ab29b6
|
data/README.md
CHANGED
data/lib/constructorio.rb
CHANGED
@@ -13,7 +13,10 @@ begin
|
|
13
13
|
rescue LoadError
|
14
14
|
end
|
15
15
|
|
16
|
+
class MissingItemName < StandardError; end
|
17
|
+
|
16
18
|
module ConstructorIO
|
19
|
+
|
17
20
|
class << self
|
18
21
|
attr_accessor :configuration
|
19
22
|
end
|
@@ -26,50 +29,94 @@ module ConstructorIO
|
|
26
29
|
yield(configuration)
|
27
30
|
end
|
28
31
|
|
29
|
-
|
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
|
30
37
|
|
31
|
-
|
32
|
-
|
33
|
-
|
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 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
|
34
47
|
|
35
|
-
|
36
|
-
|
37
|
-
updated_fields.each do |field|
|
38
|
-
record.class.send(:add_record, record[field.to_sym], autocomplete_key)
|
48
|
+
field_names.each do |field|
|
49
|
+
ConstructorIO::Fields.instance.add(self.model_name, field)
|
39
50
|
end
|
40
|
-
end
|
41
51
|
|
42
|
-
|
52
|
+
# transform the data
|
53
|
+
transformed = {}
|
43
54
|
fields.each do |field|
|
44
|
-
|
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
|
45
73
|
end
|
46
74
|
end
|
47
75
|
end
|
48
76
|
|
49
|
-
|
50
|
-
|
51
|
-
|
77
|
+
module InstanceMethods
|
78
|
+
def constructorio_add_record(value, metadata = {}, autocomplete_key)
|
79
|
+
constructorio_call_api("post", value, metadata, autocomplete_key)
|
80
|
+
end
|
52
81
|
|
53
|
-
|
54
|
-
|
55
|
-
|
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, '')
|
56
104
|
|
57
|
-
|
58
|
-
|
59
|
-
def call_api(method, value, autocomplete_key)
|
60
|
-
@api_token = ConstructorIO.configuration.api_token
|
61
|
-
@api_url = ConstructorIO.configuration.api_url || "https://ac.constructor.io/"
|
62
|
-
@http_client ||= Faraday.new(url: @api_url)
|
63
|
-
@http_client.basic_auth(@api_token, '')
|
64
|
-
response = @http_client.send(method) do |request|
|
65
|
-
request.url "/v1/item?autocomplete_key=#{autocomplete_key}"
|
66
|
-
request.headers['Content-Type'] = 'application/json'
|
67
|
-
request.body = %Q|{"item_name": "#{value}"}|
|
105
|
+
request_body = constructorio_make_request_body(value, metadata)
|
106
|
+
constructorio_send_request(method, @http_client, request_body, autocomplete_key)
|
68
107
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
73
120
|
end
|
74
121
|
end
|
75
122
|
end
|
data/lib/constructorio/fields.rb
CHANGED
data/test/constructorio_test.rb
CHANGED
@@ -1,48 +1,106 @@
|
|
1
1
|
require_relative 'test_helper'
|
2
2
|
|
3
3
|
class ConstructorIOTest < MiniTest::Test
|
4
|
-
def
|
4
|
+
def test_add_record_makes_request
|
5
5
|
person = Person.new(
|
6
6
|
first_name: "Steven",
|
7
7
|
last_name: "Lai",
|
8
8
|
address: "New York"
|
9
9
|
)
|
10
|
-
Person.expects(:call_api).with("post", "Steven", "person_autocomplete_key")
|
11
10
|
|
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
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_add_record_sends_request
|
63
|
+
person = Person.new(
|
64
|
+
first_name: "Steven",
|
65
|
+
last_name: "Lai",
|
66
|
+
address: "New York"
|
67
|
+
)
|
68
|
+
|
69
|
+
person.expects(:constructorio_send_request)
|
12
70
|
assert person.save
|
13
71
|
end
|
14
72
|
|
15
|
-
def
|
16
|
-
Person.
|
73
|
+
def test_delete_record_makes_request
|
74
|
+
Person.any_instance.stubs(:constructorio_call_api)
|
17
75
|
person = Person.create(
|
18
76
|
first_name: "Ronald",
|
19
77
|
last_name: "McDonald",
|
20
78
|
address: "Disneyland"
|
21
79
|
)
|
22
80
|
|
23
|
-
|
81
|
+
person.expects(:constructorio_call_api).with("delete", "Ronald", has_entry('test_proc', instance_of(Proc)),"person_autocomplete_key")
|
24
82
|
person.destroy
|
25
83
|
end
|
26
84
|
|
27
|
-
def
|
85
|
+
def test_add_record_without_key_uses_default_key
|
28
86
|
person = PersonNoKey.new(
|
29
87
|
first_name: "Steven",
|
30
88
|
last_name: "Lai",
|
31
89
|
address: "New York"
|
32
90
|
)
|
33
91
|
|
34
|
-
|
92
|
+
person.expects(:constructorio_call_api).with("post", "Lai", anything, ConstructorIO.configuration.autocomplete_key)
|
35
93
|
assert person.save
|
36
94
|
end
|
37
95
|
|
38
|
-
def
|
39
|
-
Person.expects(:
|
96
|
+
def test_fields_are_tracked
|
97
|
+
Person.any_instance.expects(:constructorio_call_api).with("post", "Ronald", anything, "person_autocomplete_key")
|
40
98
|
person = Person.create(
|
41
99
|
first_name: "Ronald",
|
42
100
|
last_name: "McDonald",
|
43
101
|
address: "Disneyland"
|
44
102
|
)
|
45
103
|
|
46
|
-
assert_equal ConstructorIO::Fields.instance.list(
|
104
|
+
assert_equal ConstructorIO::Fields.instance.list('Person'), ["first_name"]
|
47
105
|
end
|
48
106
|
end
|
data/test/test_helper.rb
CHANGED
@@ -24,17 +24,26 @@ ConstructorIO.configure do |config|
|
|
24
24
|
end
|
25
25
|
|
26
26
|
class Person < ActiveRecord::Base
|
27
|
-
|
27
|
+
include ConstructorIO
|
28
|
+
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
|
28
36
|
|
29
|
-
|
37
|
+
class PersonSimple < ActiveRecord::Base
|
38
|
+
self.table_name = 'people'
|
39
|
+
include ConstructorIO
|
40
|
+
autocomplete [ 'first_name' ]
|
30
41
|
end
|
31
42
|
|
32
43
|
class PersonNoKey < ActiveRecord::Base
|
33
44
|
self.table_name = 'people'
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
autocomplete ['last_name']
|
45
|
+
include ConstructorIO
|
46
|
+
autocomplete [{'attribute' => 'last_name'}]
|
38
47
|
end
|
39
48
|
|
40
49
|
class FakeView
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: constructorio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Lai
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|