offline_lookup 1.0.0 → 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 +4 -4
- data/README.md +15 -0
- data/lib/offline_lookup/active_record.rb +20 -2
- data/lib/offline_lookup/base.rb +1 -46
- data/lib/offline_lookup/builder.rb +78 -17
- 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: 3f2b36619ce0489bb3be9209e0c6f375d6ad7b7f
|
4
|
+
data.tar.gz: 2a8b0b21903a8010032c6f99b9cfa5cfb7b5069d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b1e8325950ade06e5daeeece7c496d717c26412c7be90119395442ef69f8cbd03f78b9dff2e9e1afb04dbd64710b5c7439215dce37da6683ce81a3f18eead93a
|
7
|
+
data.tar.gz: bf7fa6108c54b9dc3946d6ead0338e56f4a0996db3aabd14d83c75dc682694118c060a8bd66b5bce289bccc45e01c8e677b2a2891b31635395ba27d73ae10978
|
data/README.md
CHANGED
@@ -138,6 +138,21 @@ end
|
|
138
138
|
Admin.id_for_name("John Doe")
|
139
139
|
```
|
140
140
|
|
141
|
+
You can also define your own method of generaing the lookup name using the `:transform` options. The default is to ust the field, or delimiter-concatentaed fields. To specify a transofmation, provide a lambda whose arguments are the fields being used by OfflineLookup
|
142
|
+
|
143
|
+
```
|
144
|
+
class Admin < ActiveRecord::Base
|
145
|
+
use_offline_lookup :lastname, transform: ->(lastname){"lookup_#{lastname}"}
|
146
|
+
end
|
147
|
+
```
|
148
|
+
|
149
|
+
Or for multiple fields
|
150
|
+
```
|
151
|
+
class Admin < ActiveRecord::Base
|
152
|
+
use_offline_lookup :firstname, :lastname, transform: ->(first, last){"#{first.first}_#{last}"}
|
153
|
+
end
|
154
|
+
```
|
155
|
+
|
141
156
|
## Known Issues
|
142
157
|
|
143
158
|
If two entries in the table have the same value in the specified field, all but one will get overwritten.
|
@@ -3,7 +3,7 @@ module OfflineLookup
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
after_create :get_offline_lookup_values
|
6
|
+
after_create :get_offline_lookup_values, :add_offline_lookup
|
7
7
|
after_destroy :get_offline_lookup_values
|
8
8
|
end
|
9
9
|
|
@@ -11,6 +11,15 @@ module OfflineLookup
|
|
11
11
|
self.class.get_offline_lookup_values
|
12
12
|
end
|
13
13
|
|
14
|
+
def offline_lookup_value
|
15
|
+
self.class.offline_lookup_value(*offline_lookup_options[:fields].map{|f| self.attributes[f.to_s]})
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_offline_lookup
|
19
|
+
builder = OfflineLookup::Builder.new(self.class, self.offline_lookup_options)
|
20
|
+
builder.add_lookup(self.attributes[builder.key], offline_lookup_value)
|
21
|
+
end
|
22
|
+
|
14
23
|
module ClassMethods
|
15
24
|
def use_offline_lookup(*fields, key: "id", identity_methods: false, lookup_methods: false, compact: false, delimiter: " ", name: fields.join(delimiter), transform: nil)
|
16
25
|
class_attribute :offline_lookup_values, :offline_lookup_options
|
@@ -30,13 +39,22 @@ module OfflineLookup
|
|
30
39
|
include OfflineLookup::Base
|
31
40
|
end
|
32
41
|
|
42
|
+
def offline_lookup_value(*fields)
|
43
|
+
if offline_lookup_options[:transform].present?
|
44
|
+
offline_lookup_options[:transform].call(*fields.map(&:to_s))
|
45
|
+
else
|
46
|
+
fields.map(&:to_s).join(offline_lookup_options[:delimiter])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
33
50
|
def get_offline_lookup_values
|
34
51
|
self.offline_lookup_values = self.all.pluck(offline_lookup_options[:key], *offline_lookup_options[:fields]).map do |key, *fields|
|
35
52
|
fields.compact! if offline_lookup_options[:compact]
|
36
53
|
value = offline_lookup_options[:transform].present? ? offline_lookup_options[:transform].call(*fields.map(&:to_s)) : fields.map(&:to_s).join(offline_lookup_options[:delimiter])
|
37
|
-
[key, value]
|
54
|
+
[key, value.to_s]
|
38
55
|
end.to_h.freeze
|
39
56
|
end
|
57
|
+
|
40
58
|
end
|
41
59
|
end
|
42
60
|
end
|
data/lib/offline_lookup/base.rb
CHANGED
@@ -3,52 +3,7 @@ module OfflineLookup
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
|
7
|
-
|
8
|
-
### define value-named methods such as :two_hour_id and :two_hour?
|
9
|
-
|
10
|
-
self.offline_lookup_values.each do |key, value|
|
11
|
-
# class method: get key value (e.g. FooType.bar_id)
|
12
|
-
define_singleton_method(builder.key_method_name(value)) do
|
13
|
-
key
|
14
|
-
end
|
15
|
-
|
16
|
-
# instance method: true if instance is of named type (e.g. FooType.first.bar?)
|
17
|
-
if self.offline_lookup_options[:identity_methods]
|
18
|
-
define_method(builder.indentiy_method_name(value)) do
|
19
|
-
self.attributes[self.offline_lookup_options[:key]] == key
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# class method: get instance by named method (e.g. FooType.bar)
|
24
|
-
# not "Offline", but lookup by indexed key. Also, synactic sugar.
|
25
|
-
if self.offline_lookup_options[:lookup_methods]
|
26
|
-
define_singleton_method(builder.lookup_method_name(value)) do
|
27
|
-
key = self.offline_lookup_values.find{|k, v| v.to_s == value.to_s}.try(:first)
|
28
|
-
find(key)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
# class method: get instance using more general `lookup` method
|
33
|
-
# Just as not "offline" as above, but less dangerous / more robust to any db value
|
34
|
-
define_singleton_method :lookup do |value|
|
35
|
-
key = self.offline_lookup_values.find{|k, v| v.to_s == value.to_s}.try(:first)
|
36
|
-
find_by(id: key)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
### define statically-named methods where you pass in the named value, e.g., id_for_name(:two_hour)
|
42
|
-
# e.g. FooType.name_for_id(1)
|
43
|
-
define_singleton_method(builder.field_for_key_method_name) do |key_value|
|
44
|
-
self.offline_lookup_values[key_value]
|
45
|
-
end
|
46
|
-
|
47
|
-
# e.g. FooType.id_for_name("Bar")
|
48
|
-
define_singleton_method(builder.key_for_field_method_name) do |field_value|
|
49
|
-
self.offline_lookup_values.find{|k, v| v.to_s == field_value.to_s}.try(:first)
|
50
|
-
end
|
51
|
-
|
6
|
+
OfflineLookup::Builder.new(self, self.offline_lookup_options).build
|
52
7
|
end
|
53
8
|
end
|
54
9
|
end
|
@@ -1,15 +1,46 @@
|
|
1
1
|
module OfflineLookup
|
2
2
|
class Builder
|
3
|
-
|
3
|
+
attr_reader :fields, :key, :name
|
4
|
+
def initialize(model, options)
|
5
|
+
@model = model
|
4
6
|
@fields = options[:fields]
|
5
7
|
@key = options[:key]
|
6
8
|
@name = options[:name]
|
9
|
+
@build_identity_methods = options[:identity_methods]
|
10
|
+
@build_lookup_methods = options[:lookup_methods]
|
11
|
+
@modyule = get_module || create_module
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_module
|
15
|
+
@model.const_defined?("OfflineLookupMethods") && @model::OfflineLookupMethods
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_module
|
19
|
+
@modyule = Module.new
|
20
|
+
@modyule.extend ActiveSupport::Concern
|
21
|
+
@modyule.const_set("ClassMethods", Module.new)
|
22
|
+
@model.const_set("OfflineLookupMethods", @modyule)
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
@model.offline_lookup_values.each do |key, value|
|
27
|
+
add_lookup(key, value)
|
28
|
+
end
|
29
|
+
add_name_for_key_method
|
30
|
+
add_key_for_name_method
|
31
|
+
add_static_lookup_method
|
32
|
+
@model.include @modyule
|
33
|
+
end
|
34
|
+
|
35
|
+
def add_lookup(key, value)
|
36
|
+
add_key_lookup_method(key, value)
|
37
|
+
add_identity_method(key, value) if @build_identity_methods
|
38
|
+
add_lookup_method(key, value) if @build_lookup_methods
|
7
39
|
end
|
8
40
|
|
9
41
|
def sanitize(string)
|
10
|
-
#:methodize went away. Where did it go?
|
11
42
|
#1. Replace illegal chars and _ boundaries with " " boundary
|
12
|
-
string = string.gsub(/[^a-zA-Z\d]+/," ").strip
|
43
|
+
string = string.to_s.gsub(/[^a-zA-Z\d]+/," ").strip
|
13
44
|
#2. Insert " " boundary at snake-case boundaries
|
14
45
|
string.gsub!(/([a-z])([A-Z])/){|s| "#{$1} #{$2}"}
|
15
46
|
#3. underscore
|
@@ -20,28 +51,58 @@ module OfflineLookup
|
|
20
51
|
return string
|
21
52
|
end
|
22
53
|
|
23
|
-
# e.g
|
24
|
-
def
|
25
|
-
|
54
|
+
# Get key value (e.g. FooType.bar_id)
|
55
|
+
def add_key_lookup_method(key, value)
|
56
|
+
@modyule::ClassMethods.instance_exec(self, key, value) do |builder, key, value|
|
57
|
+
define_method builder.sanitize("#{value}_#{builder.key}") do
|
58
|
+
key
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Return true iff instance is of named type (e.g. FooType.first.bar?)
|
64
|
+
def add_identity_method(key, value)
|
65
|
+
@modyule.instance_exec(self, key, value) do |builder, key, value|
|
66
|
+
define_method builder.sanitize(value) + "?" do
|
67
|
+
self.attributes[builder.key] == key
|
68
|
+
end
|
69
|
+
end
|
26
70
|
end
|
27
71
|
|
28
|
-
|
29
|
-
|
72
|
+
# Get instance by named method (e.g. FooType.bar) (Not offline, but syntactic sugar)
|
73
|
+
def add_lookup_method(key, value)
|
74
|
+
@modyule::ClassMethods.instance_exec(self, key, value) do |builder, key, value|
|
75
|
+
define_method builder.sanitize(value) do
|
76
|
+
find_by(builder.key => self.offline_lookup_values.key(value.to_s))
|
77
|
+
end
|
78
|
+
end
|
30
79
|
end
|
31
80
|
|
32
|
-
# e.g
|
33
|
-
def
|
34
|
-
|
81
|
+
# e.g. FooType.name_for_id(1)
|
82
|
+
def add_name_for_key_method
|
83
|
+
@modyule::ClassMethods.instance_exec(self) do |builder|
|
84
|
+
define_method builder.sanitize("#{builder.name}_for_#{builder.key}") do |key|
|
85
|
+
self.offline_lookup_values[key]
|
86
|
+
end
|
87
|
+
end
|
35
88
|
end
|
36
89
|
|
37
|
-
# e.g.
|
38
|
-
def
|
39
|
-
|
90
|
+
# e.g. FooType.id_for_name("Bar")
|
91
|
+
def add_key_for_name_method
|
92
|
+
@modyule::ClassMethods.instance_exec(self) do |builder|
|
93
|
+
define_method builder.sanitize("#{builder.key}_for_#{builder.name}") do |value|
|
94
|
+
self.offline_lookup_values.key(value.to_s)
|
95
|
+
end
|
96
|
+
end
|
40
97
|
end
|
41
98
|
|
42
|
-
# e.g.
|
43
|
-
def
|
44
|
-
|
99
|
+
# e.g. FooType.lookup("Bar")
|
100
|
+
def add_static_lookup_method
|
101
|
+
@modyule::ClassMethods.instance_exec(self) do |builder|
|
102
|
+
define_method "lookup" do |value|
|
103
|
+
find_by(builder.key => self.offline_lookup_values.key(value.to_s))
|
104
|
+
end
|
105
|
+
end
|
45
106
|
end
|
46
107
|
|
47
108
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: offline_lookup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Schwartz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-20 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Offline indexing of small tables syntactic sugar & less db touching
|
14
14
|
email: ozydingo@gmail.com
|