offline_lookup 0.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 +7 -0
- data/lib/offline_lookup.rb +162 -0
- metadata +44 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 214a550c54e40d9f718478920e4f9ec0a4a8be16
|
4
|
+
data.tar.gz: 834b7a4a9b81da79a8fb10f23a0fe6a001c93579
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d2994fff30186971db79cbf00d7e9f8cb6dbca51ade19522e73e7a74f765b1e4e798a982a3a98f1a9ed189b0fc33b7d710cc143e847601e483c619f2131cffc
|
7
|
+
data.tar.gz: 716e5f920f9492a1f3951eb5dc476625b4c2f031e875166602969c912577da1a65803462962cdd8ba69ccb7cc065b5a2f4c564afae7d98539e00d2d623833da7
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# IMPORTANT: don't use this for models that have a lot of data!!
|
2
|
+
#
|
3
|
+
# This is basically a in-memory pseudo-index intended to speed up quick, repeated
|
4
|
+
# finds of index table values without trips to an external db machine.
|
5
|
+
# It's also nicer syntax, e.g:
|
6
|
+
# TurnaroundLevel.two_hour_id
|
7
|
+
# TurnaroundLevel.quick_lookup("Two Hour")
|
8
|
+
# Service.last.turnaround_level.two_hour?
|
9
|
+
#
|
10
|
+
# In any ActiveRecord::Base subclass, use:
|
11
|
+
# >> use_offline_id_lookup column_name
|
12
|
+
# to define class methods that can convert between id and the corresponding
|
13
|
+
# value in column_name for the class, without going to the database
|
14
|
+
#
|
15
|
+
# column_name defaults to :name, but can be any column of the table
|
16
|
+
# use the :key keyword arg if you're interested in a key colun other than :id
|
17
|
+
#
|
18
|
+
# Usage example:
|
19
|
+
# class JobType < ActiveRecord::Base
|
20
|
+
# use_offline_id_lookup
|
21
|
+
# ...
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# This gives you:
|
25
|
+
# JobType.editing_id
|
26
|
+
# #=> 1
|
27
|
+
# JobType.name_for_id(1)
|
28
|
+
# #=> 'Editing'
|
29
|
+
# JobType.id_for_name('Editing')
|
30
|
+
# #=> 1
|
31
|
+
# with no db queries.
|
32
|
+
#
|
33
|
+
# You can use this on multiple column names (currently
|
34
|
+
# need to call use_offline_id_lookup once for each column name)
|
35
|
+
# class InvoiceLineItemType < ActiveRecord::Base
|
36
|
+
# use_offline_id_lookup :name
|
37
|
+
# use_offline_id_lookup :accounting_label
|
38
|
+
# ...
|
39
|
+
#
|
40
|
+
# You get InvoiceLineItemType.name_for_id(id) and
|
41
|
+
# InvoiceLineItemType.account_label_for_id(id), etc.
|
42
|
+
# Beware that if any value occurs more than once,
|
43
|
+
# either in the same column or different columns for
|
44
|
+
# which use_offline_id_lookup was called, the <name>_id
|
45
|
+
# method will only use the last column for which it was observed.
|
46
|
+
|
47
|
+
|
48
|
+
#!!!
|
49
|
+
# TODO: requires :methodize
|
50
|
+
#!!!
|
51
|
+
|
52
|
+
# TODO: provide multiple column names in a single call (e.g. firstname, lastname)
|
53
|
+
# TODO: support multiple offline lookups per model
|
54
|
+
# TODO: support scope arg in use_offline_lookup (partial index)
|
55
|
+
|
56
|
+
module OfflineLookup
|
57
|
+
module ActiveRecord
|
58
|
+
def use_offline_lookup(field = :name, key: :id, lookup_methods: true)
|
59
|
+
class_attribute :offline_lookup_values, :offline_lookup_options
|
60
|
+
self.offline_lookup_options = {field: field.to_s, key: key.to_s, lookup_methods: lookup_methods}.freeze
|
61
|
+
self.offline_lookup_values = self.all.pluck(key, field).to_h.freeze
|
62
|
+
|
63
|
+
include OfflineLookup::Base
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Builder
|
68
|
+
def initialize(options)
|
69
|
+
@field = options[:field]
|
70
|
+
@key = options[:key]
|
71
|
+
end
|
72
|
+
|
73
|
+
def sanitize(string)
|
74
|
+
#:methodize went away. Where did it go?
|
75
|
+
#1. Replace illegal chars and _ boundaries with " " boundary
|
76
|
+
string = string.gsub(/[^a-zA-Z\d]+/," ").strip
|
77
|
+
#2. Insert " " boundary at snake-case boundaries
|
78
|
+
string.gsub!(/([a-z])([A-Z])/){|s| "#{$1} #{$2}"}
|
79
|
+
#3. underscore
|
80
|
+
string.gsub!(/\s+/, "_")
|
81
|
+
string.downcase!
|
82
|
+
#4. Append underscore if name begins with digit
|
83
|
+
string = "_#{string}" if string.length == 0 || string[0] =~ /\d/
|
84
|
+
return string
|
85
|
+
end
|
86
|
+
|
87
|
+
# e.g., :two_hour_id
|
88
|
+
def key_method_name(value)
|
89
|
+
sanitize "#{value}_#{@key}"
|
90
|
+
end
|
91
|
+
|
92
|
+
def lookup_method_name(value)
|
93
|
+
sanitize value.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
# e.g., :two_hour?
|
97
|
+
def indentiy_method_name(value)
|
98
|
+
lookup_method_name(value) + "?"
|
99
|
+
end
|
100
|
+
|
101
|
+
# e.g. :name_for_id(id)
|
102
|
+
def field_for_key_method_name
|
103
|
+
sanitize "#{@field}_for_#{@key}"
|
104
|
+
end
|
105
|
+
|
106
|
+
# e.g. :id_for_name(name)
|
107
|
+
def key_for_field_method_name
|
108
|
+
sanitize "#{@key}_for_#{@field}"
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
module Base
|
114
|
+
extend ActiveSupport::Concern
|
115
|
+
|
116
|
+
included do
|
117
|
+
builder = OfflineLookup::Builder.new(self.offline_lookup_options)
|
118
|
+
|
119
|
+
### define value-named methods such as :two_hour_id and :two_hour?
|
120
|
+
|
121
|
+
self.offline_lookup_values.each do |key, value|
|
122
|
+
define_singleton_method(builder.key_method_name(value)) do
|
123
|
+
key
|
124
|
+
end
|
125
|
+
|
126
|
+
define_singleton_method(builder.indentiy_method_name(value)) do
|
127
|
+
self.attributes[self.offline_lookup_options[:key]] == key
|
128
|
+
end
|
129
|
+
|
130
|
+
# not "Offline", but lookup by indexed key. Also, synactic sugar.
|
131
|
+
if self.offline_lookup_options[:lookup_methods]
|
132
|
+
define_singleton_method(builder.lookup_method_name(value)) do
|
133
|
+
key = self.offline_lookup_values.find{|k, v| v.to_s == value.to_s}.first
|
134
|
+
find(key)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
### define statically-named methods where you pass in the named value, e.g., id_for_name(:two_hour)
|
141
|
+
|
142
|
+
define_singleton_method(builder.field_for_key_method_name) do |key_value|
|
143
|
+
self.offline_lookup_values[key_value]
|
144
|
+
end
|
145
|
+
|
146
|
+
define_singleton_method(builder.key_for_field_method_name) do |field_value|
|
147
|
+
self.offline_lookup_values.find{|k, v| v.to_s == field_value.to_s}.first
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
151
|
+
|
152
|
+
module ClassMethods
|
153
|
+
def quick_lookup(value)
|
154
|
+
key = self.offline_lookup_values.find{|k, v| v.to_s == value.to_s}.first
|
155
|
+
find(key)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
ActiveRecord::Base.extend OfflineLookup::ActiveRecord
|
metadata
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: offline_lookup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Schwartz
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-04-13 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Offline indexing of small tables for speed & convenience
|
14
|
+
email: ozydingo@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/offline_lookup.rb
|
20
|
+
homepage:
|
21
|
+
licenses:
|
22
|
+
- MIT
|
23
|
+
metadata: {}
|
24
|
+
post_install_message:
|
25
|
+
rdoc_options: []
|
26
|
+
require_paths:
|
27
|
+
- lib
|
28
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
34
|
+
requirements:
|
35
|
+
- - ">="
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
requirements: []
|
39
|
+
rubyforge_project:
|
40
|
+
rubygems_version: 2.4.5
|
41
|
+
signing_key:
|
42
|
+
specification_version: 4
|
43
|
+
summary: Offline lookup
|
44
|
+
test_files: []
|