empty_eye 0.4.2 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +6 -1
- data/lib/empty_eye/active_record/base.rb +41 -85
- data/lib/empty_eye/associations/shard_association_scope.rb +1 -1
- data/lib/empty_eye/associations/shard_has_one_association.rb +1 -1
- data/lib/empty_eye/persistence.rb +4 -4
- data/lib/empty_eye/{primary_view_extension.rb → primary_shard.rb} +30 -43
- data/lib/empty_eye/relation.rb +2 -65
- data/lib/empty_eye/shard.rb +86 -111
- data/lib/empty_eye/shard_collection.rb +192 -0
- data/lib/empty_eye/shard_wrangler.rb +300 -0
- data/lib/empty_eye/version.rb +1 -1
- data/lib/empty_eye.rb +5 -4
- data/spec/spec_helper.rb +0 -6
- metadata +7 -7
- data/lib/empty_eye/view_extension.rb +0 -114
- data/lib/empty_eye/view_extension_collection.rb +0 -227
@@ -1,227 +0,0 @@
|
|
1
|
-
module EmptyEye
|
2
|
-
class ViewExtensionCollection
|
3
|
-
|
4
|
-
#a collection of all the view_extensions
|
5
|
-
#these are wranglers for the shards
|
6
|
-
#uses 'array' as a proxy
|
7
|
-
#performs array methods by passing things off in method missing
|
8
|
-
|
9
|
-
def initialize(parent)
|
10
|
-
@parent = parent
|
11
|
-
@array = []
|
12
|
-
end
|
13
|
-
|
14
|
-
#the proxy object for instances
|
15
|
-
def array
|
16
|
-
@array
|
17
|
-
end
|
18
|
-
|
19
|
-
#we want to see the proxy object not the class info
|
20
|
-
def inspect
|
21
|
-
array.inspect
|
22
|
-
end
|
23
|
-
|
24
|
-
#the class to which the instance belongs
|
25
|
-
def parent
|
26
|
-
@parent
|
27
|
-
end
|
28
|
-
|
29
|
-
def descend(klass)
|
30
|
-
@parent = klass
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
#add extensions based on association from parent
|
35
|
-
def association(assoc)
|
36
|
-
new_extension = ViewExtension.new(assoc)
|
37
|
-
reject! {|extension| new_extension.name == extension.name}
|
38
|
-
push(new_extension)
|
39
|
-
new_extension
|
40
|
-
end
|
41
|
-
|
42
|
-
#add primary extension; needs a table only
|
43
|
-
def primary_table(table)
|
44
|
-
push(@primary = PrimaryViewExtension.new(table, parent))
|
45
|
-
end
|
46
|
-
|
47
|
-
#generates view sql
|
48
|
-
def create_view_sql
|
49
|
-
#determine what shard will handle what columns
|
50
|
-
map_attribute_management
|
51
|
-
#start with primary table
|
52
|
-
query = primary_arel_table
|
53
|
-
|
54
|
-
#build select clause with correct table handling the appropriate columns
|
55
|
-
arel_columns.each do |arel_column|
|
56
|
-
query = query.project(arel_column)
|
57
|
-
end
|
58
|
-
|
59
|
-
#build joins
|
60
|
-
without_primary.each do |ext|
|
61
|
-
current = ext.arel_table
|
62
|
-
key = ext.foreign_key.to_sym
|
63
|
-
if ext.type_column
|
64
|
-
query = query.join(current).on(
|
65
|
-
primary.key.eq(current[key]), ext.type_column.eq(ext.type_value)
|
66
|
-
)
|
67
|
-
else
|
68
|
-
query = query.join(current).on(
|
69
|
-
primary.key.eq(current[key])
|
70
|
-
)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
#we dont need to keep this data
|
75
|
-
free_arel_columns
|
76
|
-
|
77
|
-
#STI condition if needed
|
78
|
-
if primary.sti_also?
|
79
|
-
query.where(primary.type_column.eq(primary.type_value))
|
80
|
-
end
|
81
|
-
|
82
|
-
#build view creation statement
|
83
|
-
"CREATE VIEW #{parent.table_name} AS\n#{query.to_sql}"
|
84
|
-
end
|
85
|
-
|
86
|
-
#takes the name of extension and a hash of intended updates from master instance
|
87
|
-
#returns a subset of hash with only values the extension handles
|
88
|
-
def delegate_map(name, hash)
|
89
|
-
keys = update_mapping[name] & hash.keys
|
90
|
-
keys.inject({}) do |res, col|
|
91
|
-
res[col] = hash[col] if hash[col]
|
92
|
-
res
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
#in the end this will be an array of argument arrays
|
97
|
-
#[[:validates_presence_of, :name, {}]]
|
98
|
-
#parent will call the method and associated args inheriting validations
|
99
|
-
def validations
|
100
|
-
@validations ||= []
|
101
|
-
end
|
102
|
-
|
103
|
-
#the primary extension
|
104
|
-
def primary
|
105
|
-
@primary
|
106
|
-
end
|
107
|
-
|
108
|
-
#array of shard classes
|
109
|
-
def shards
|
110
|
-
map(&:shard)
|
111
|
-
end
|
112
|
-
|
113
|
-
#this object responds to array methods
|
114
|
-
def respond_to?(m)
|
115
|
-
super || array.respond_to?(m)
|
116
|
-
end
|
117
|
-
|
118
|
-
#delegate to the array proxy when the method is missing
|
119
|
-
def method_missing(m, *args, &block)
|
120
|
-
if respond_to?(m)
|
121
|
-
array.send(m, *args, &block)
|
122
|
-
else
|
123
|
-
super
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
#we dont need to keep this data
|
128
|
-
def free_validations
|
129
|
-
@validations = nil
|
130
|
-
end
|
131
|
-
|
132
|
-
private
|
133
|
-
|
134
|
-
#all of the arel columns mapped to the right arel tables
|
135
|
-
def arel_columns
|
136
|
-
@arel_columns ||= []
|
137
|
-
end
|
138
|
-
|
139
|
-
#we dont need to keep this data
|
140
|
-
def free_arel_columns
|
141
|
-
@arel_columns = nil
|
142
|
-
end
|
143
|
-
|
144
|
-
#tracks the attributes with the view extension that will handle it
|
145
|
-
def update_mapping
|
146
|
-
@update_mapping ||= {}
|
147
|
-
end
|
148
|
-
|
149
|
-
#generate a foreign_key if it is missing
|
150
|
-
def default_foreign_key
|
151
|
-
view_name = parent.table_name.singularize
|
152
|
-
"#{view_name}_id"
|
153
|
-
end
|
154
|
-
|
155
|
-
#the primary arel table
|
156
|
-
def primary_arel_table
|
157
|
-
primary.arel_table
|
158
|
-
end
|
159
|
-
|
160
|
-
#all the tables
|
161
|
-
def tables
|
162
|
-
map(&:table)
|
163
|
-
end
|
164
|
-
|
165
|
-
#map the columns to the extension that will handle it
|
166
|
-
def map_attribute_management
|
167
|
-
#clear out what we know
|
168
|
-
arel_columns.clear
|
169
|
-
#use this to track and remove dupes
|
170
|
-
tracker = {}
|
171
|
-
each do |ext|
|
172
|
-
#mimic the parent's associations through primary shard
|
173
|
-
primary.have_one(ext)
|
174
|
-
ext.columns.each do |col|
|
175
|
-
column = col.to_sym
|
176
|
-
#skip if we already have this column
|
177
|
-
next if tracker[column]
|
178
|
-
#set to true so we wont do again
|
179
|
-
tracker[column] = true
|
180
|
-
#add the column based on the extension's arel_table
|
181
|
-
arel_columns << ext.arel_table[column]
|
182
|
-
#later we need to know how to update thing correctly
|
183
|
-
update_mapping[ext.name] = update_mapping[ext.name].to_a << col
|
184
|
-
#delegate the setter for column to shard of extension through primary shard
|
185
|
-
primary.delegate_to(column, ext) unless ext.primary
|
186
|
-
#mti class must inherit validations
|
187
|
-
add_validations(column, ext)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
#tried a cleaner solution but it wouldnt work
|
193
|
-
#here i am stealing the arguments needed from the shards
|
194
|
-
#to call the same validation on the master class (parent)
|
195
|
-
def add_validations(column, ext)
|
196
|
-
return unless ext.shard._validators[column].present?
|
197
|
-
#primary either has no validations or they have already been inherited
|
198
|
-
return if ext.primary
|
199
|
-
rtn = ext.shard._validators[column].each do |validator|
|
200
|
-
meth = case validator.class.to_s
|
201
|
-
when /presence/i then :validates_presence_of
|
202
|
-
when /acceptance/i then :validates_acceptance_of
|
203
|
-
when /numericality/i then :validates_numericality_of
|
204
|
-
when /length/i then :validates_length_of
|
205
|
-
when /inclusion/i then :validates_inclusion_of
|
206
|
-
when /format/i then :validates_format_of
|
207
|
-
when /exclusion/i then :validates_exclusion_of
|
208
|
-
when /confirmation/i then :validates_confirmation_of
|
209
|
-
when /uniqueness/i then :validates_uniqueness_of
|
210
|
-
else nil
|
211
|
-
end
|
212
|
-
if meth
|
213
|
-
args = []
|
214
|
-
args << meth
|
215
|
-
args << column
|
216
|
-
args << validator.options
|
217
|
-
validations << args
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
#return a list of extensions without primary
|
223
|
-
def without_primary
|
224
|
-
array.select {|ext| ext != primary}
|
225
|
-
end
|
226
|
-
end
|
227
|
-
end
|