offline_lookup 1.0.0 → 1.1.0

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: a980e6edb149fd22cc7c81f2986ddac4e6ca27dc
4
- data.tar.gz: dedadea949a7706a88188eb2bd0a03b31530ac34
3
+ metadata.gz: 3f2b36619ce0489bb3be9209e0c6f375d6ad7b7f
4
+ data.tar.gz: 2a8b0b21903a8010032c6f99b9cfa5cfb7b5069d
5
5
  SHA512:
6
- metadata.gz: 1bd3263c95eb71ea8a2a5f511ee075a8a893eaf56f9aedf5c40b84c5addd49ad1230e2506270f407010c719391602e713e0ec8ea641585f3af134df3ecb63a9d
7
- data.tar.gz: cdefda2de296628c482b77bd156b08213a1205d696674682524ba6e99cc3ceb1be595d50e1d280ad6fae148146e76ed7f91b1e20c6b2a80511454aadace64ac4
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
@@ -3,52 +3,7 @@ module OfflineLookup
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- builder = OfflineLookup::Builder.new(self.offline_lookup_options)
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
- def initialize(options)
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., :two_hour_id
24
- def key_method_name(value)
25
- sanitize "#{value}_#{@key}"
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
- def lookup_method_name(value)
29
- sanitize value.to_s
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., :two_hour?
33
- def indentiy_method_name(value)
34
- lookup_method_name(value) + "?"
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. :name_for_id(id)
38
- def field_for_key_method_name
39
- sanitize "#{@name}_for_#{@key}"
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. :id_for_name(name)
43
- def key_for_field_method_name
44
- sanitize "#{@key}_for_#{@name}"
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.0.0
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-19 00:00:00.000000000 Z
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