constructorio 1.0.2 → 1.0.3

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
  SHA1:
3
- metadata.gz: 40e32ccf33eeef2ae06b3df8d5dabf6502afc172
4
- data.tar.gz: 7f3388a3313802ff44c90bd9134cfdec55b47295
3
+ metadata.gz: 0afa62571df5734cb0bec7f26976b1ff8b4ed039
4
+ data.tar.gz: 8bfbffbaee6ff520ec59a6d5208ef3fd5dba5b7d
5
5
  SHA512:
6
- metadata.gz: 746be9380a15969bf924459873cf6f51818e4ccce284339e32488b049a0f6e0a93562d7c082cbbc8d2dc10a5a05579a6168288e56c08eff93070f2096f0096e9
7
- data.tar.gz: 3d2e4caa400045ee3da00cd9a0271ee42f285ad3e88fd5b40aacfafc494459a2c760f40c8183f030208f6476546d95bc2cb8c1cc940578a016e2f2b17da5f6df
6
+ metadata.gz: 479bdfc0a8a29dfbcb15254af5f36a88438db4763f53d5ccbaa3a67cd5af066ac9f673483b154e36e788b9f47daa4f3e093b36a4dece7e899dd0581804f9db8b
7
+ data.tar.gz: cfeca1527e5c9f1d543e38a514e41e02310c5a181d9e11c29effcbd288d1a68fb8c2a85468317ebf7efe2fcb8778927518c3a99fb893069b600fd3e8d5ab29b6
data/README.md CHANGED
@@ -31,7 +31,7 @@ To add autocomplete to a model:
31
31
 
32
32
  ```
33
33
  class MyModel < ActiveRecord::Base
34
- extend ConstructorIO
34
+ include ConstructorIO
35
35
  autocomplete(['attribute1', 'attribute2'])
36
36
  end
37
37
 
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
- def autocomplete(fields, autocomplete_key = ConstructorIO.configuration.autocomplete_key)
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
- fields.each do |field|
32
- ConstructorIO::Fields.instance.add(self.model_name, field)
33
- end
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
- after_save do |record|
36
- updated_fields = record.changed.select { |c| fields.include? c }
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
- before_destroy do |record|
52
+ # transform the data
53
+ transformed = {}
43
54
  fields.each do |field|
44
- record.class.send(:delete_record, record[field.to_sym], autocomplete_key)
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
- def add_record(value, autocomplete_key)
50
- call_api("post", value, autocomplete_key)
51
- end
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
- def delete_record(value, autocomplete_key)
54
- call_api("delete", value, autocomplete_key)
55
- end
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
- private
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
- if response.status.to_s =~ /^2/
70
- return nil
71
- else
72
- return response.status
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
@@ -10,9 +10,9 @@ module ConstructorIO
10
10
  @set = {}
11
11
  end
12
12
 
13
- def add(model, field)
14
- @set[model] ||= {}
15
- @set[model][field] = 1
13
+ def add(model_name, field)
14
+ @set[model_name] ||= {}
15
+ @set[model_name][field] = 1
16
16
  end
17
17
 
18
18
  def list(model_name)
@@ -1,3 +1,3 @@
1
1
  module ConstructorIO
2
- VERSION = "1.0.2"
2
+ VERSION = "1.0.3"
3
3
  end
@@ -1,48 +1,106 @@
1
1
  require_relative 'test_helper'
2
2
 
3
3
  class ConstructorIOTest < MiniTest::Test
4
- def test_add_record
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 test_delete_record
16
- Person.expects(:call_api).with("post", "Ronald", "person_autocomplete_key")
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
- Person.expects(:call_api).with("delete", "Ronald", "person_autocomplete_key")
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 test_add_record_without_key
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
- PersonNoKey.expects(:call_api).with("post", "Lai", ConstructorIO.configuration.autocomplete_key)
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 test_fields
39
- Person.expects(:call_api).with("post", "Ronald", "person_autocomplete_key")
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("Person"), ["first_name"]
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
- extend ConstructorIO
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
- autocomplete ['first_name'], "person_autocomplete_key"
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
- extend ConstructorIO
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.2
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-08 00:00:00.000000000 Z
11
+ date: 2015-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord