CITIEsForRAILS 0.0.3
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.
- data/CITIEsForRAILS.gemspec +33 -0
- data/Manifest +5 -0
- data/Rakefile +15 -0
- data/lib/citiesforrails/acts_as_cities.rb +325 -0
- data/lib/citiesforrails/core_ext.rb +282 -0
- data/lib/citiesforrails.rb +3 -0
- metadata +81 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{CITIEsForRAILS}
|
5
|
+
s.version = "0.0.3"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Laurent Buffat & Pierre-Emmanuel JOUVE"]
|
9
|
+
s.date = %q{2011-02-15}
|
10
|
+
s.description = %q{CITIEsForRAILS (Class Inheritance & Table Iheritance Embeddings For RAILS) is a solution that extends Single/Multiple/Class Table Inheritance. This solution is based on classical Ruby class inheritance, single table inheritance as well as DB views.
|
11
|
+
|
12
|
+
|
13
|
+
For Full Information GO TO : http://altrabio.github.com/CITIEsForRAILS/}
|
14
|
+
s.email = %q{citiesforrails @nospam@ gmail.com}
|
15
|
+
s.extra_rdoc_files = ["lib/citiesforrails.rb", "lib/citiesforrails/acts_as_cities.rb", "lib/citiesforrails/core_ext.rb"]
|
16
|
+
s.files = ["Rakefile", "lib/citiesforrails.rb", "lib/citiesforrails/acts_as_cities.rb", "lib/citiesforrails/core_ext.rb", "Manifest", "CITIEsForRAILS.gemspec"]
|
17
|
+
s.homepage = %q{https://github.com/altrabio/CITIEsForRAILS}
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "CITIEsForRAILS", "--main", "README"]
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rubyforge_project = %q{citiesforrails}
|
21
|
+
s.rubygems_version = %q{1.3.7}
|
22
|
+
s.summary = %q{CITIEsForRAILS (Class Inheritance & Table Iheritance Embeddings For RAILS) is a solution that extends Single/Multiple/Class Table Inheritance. This solution is based on classical Ruby class inheritance, single table inheritance as well as DB views. For Full Information GO TO : http://altrabio.github.com/CITIEsForRAILS/}
|
23
|
+
|
24
|
+
if s.respond_to? :specification_version then
|
25
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
26
|
+
s.specification_version = 3
|
27
|
+
|
28
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
29
|
+
else
|
30
|
+
end
|
31
|
+
else
|
32
|
+
end
|
33
|
+
end
|
data/Manifest
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('CITIEsForRAILS', '0.0.3') do |p|
|
6
|
+
p.description = "CITIEsForRAILS (Class Inheritance & Table Iheritance Embeddings For RAILS) is a solution that extends Single/Multiple/Class Table Inheritance. This solution is based on classical Ruby class inheritance, single table inheritance as well as DB views.
|
7
|
+
|
8
|
+
|
9
|
+
For Full Information GO TO : http://altrabio.github.com/CITIEsForRAILS/"
|
10
|
+
p.url = "https://github.com/altrabio/CITIEsForRAILS"
|
11
|
+
p.author = "Laurent Buffat & Pierre-Emmanuel JOUVE"
|
12
|
+
p.email = "citiesforrails @nospam@ gmail.com"
|
13
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
14
|
+
p.development_dependencies = []
|
15
|
+
end
|
@@ -0,0 +1,325 @@
|
|
1
|
+
module Cities
|
2
|
+
|
3
|
+
def self.included(base)
|
4
|
+
#When a class includes a module the module’s self.included method will be invoked.
|
5
|
+
base.send :extend, ClassMethods
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
#------------------------------------------------------------------------------------------------------------------------
|
10
|
+
#
|
11
|
+
# methods that will be used for the class
|
12
|
+
#
|
13
|
+
#------------------------------------------------------------------------------------------------------------------------
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
# any method placed here will apply to classes
|
17
|
+
|
18
|
+
|
19
|
+
def acts_as_cities(options = {}) #options hash see below
|
20
|
+
|
21
|
+
|
22
|
+
db_type_field = (options[:db_type_field] || :type).to_s #:db_type_field = option for setting the inheritance columns, default value = 'type'
|
23
|
+
table_name = (options[:table_name] || self.name.tableize.gsub(/\//,'_')).to_s #:table_name = option for setting the name of the current class table_name, default value = 'tableized(current class name)'
|
24
|
+
|
25
|
+
set_inheritance_column "#{db_type_field}"
|
26
|
+
|
27
|
+
if(self.superclass!=ActiveRecord::Base)
|
28
|
+
#------------------------------------------------------------------------------------------------------------------------
|
29
|
+
#
|
30
|
+
# methods that will be used for the NON mother class
|
31
|
+
#
|
32
|
+
#------------------------------------------------------------------------------------------------------------------------
|
33
|
+
puts "acts_as_cities -> NON mother class"
|
34
|
+
|
35
|
+
set_table_name "view_#{table_name}"
|
36
|
+
aaa=create_class_part_of self# these 2 lines are there for the creation of class PartOf (which is a class of the current class)
|
37
|
+
self.const_set("PartOf",aaa) # it will stand for the write table of the current class
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
def self.delete(id) #overrides delete to delete every pieces of information about this record wherever it may be stored
|
42
|
+
if RAILS_ENV == 'development'
|
43
|
+
puts "delete de classe = #{self.name}"
|
44
|
+
end
|
45
|
+
return self.delete(id) if self == self.mother_class #if the class of the record is the mother class then call with the id of the object
|
46
|
+
#if the class of the record is not the mother class then
|
47
|
+
if RAILS_ENV == 'development'
|
48
|
+
puts "2->delete de classe = #{self.name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
if self.respond_to?('has_a_part_of?') # eventually delete pieces of information stored in the table associated to the class of the object (if there is such a table)
|
52
|
+
if self.has_a_part_of? && (self.superclass==self.mother_class || self::PartOf!=self.superclass::PartOf) #SHOW TO LB implique moins de SQL
|
53
|
+
if RAILS_ENV == 'development'
|
54
|
+
puts("has a part of")
|
55
|
+
end
|
56
|
+
self::PartOf.delete(id)
|
57
|
+
else
|
58
|
+
if RAILS_ENV == 'development'
|
59
|
+
puts "no part of"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
if RAILS_ENV == 'development'
|
65
|
+
puts "3->delete de classe = #{self.name}"
|
66
|
+
end
|
67
|
+
|
68
|
+
self.superclass.delete(id) # call the delete method associated to the super class of the current class with the id the object
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
send :include, InstanceMethods1
|
73
|
+
else
|
74
|
+
#------------------------------------------------------------------------------------------------------------------------
|
75
|
+
#
|
76
|
+
# methods that will be used for the mother class
|
77
|
+
#
|
78
|
+
#------------------------------------------------------------------------------------------------------------------------
|
79
|
+
after_save :updatetype
|
80
|
+
|
81
|
+
|
82
|
+
if RAILS_ENV == 'development'
|
83
|
+
puts "acts_as_cities -> MOTHER class"
|
84
|
+
end
|
85
|
+
set_table_name="#{table_name}"
|
86
|
+
|
87
|
+
def self.mother_class #returns the mother class (the highest inherited class before ActiveRecord)
|
88
|
+
if(self.superclass!=ActiveRecord::Base)
|
89
|
+
self.superclass.mother_class
|
90
|
+
else
|
91
|
+
return self
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
def self.find(*args) #overrides find to get more informations
|
98
|
+
|
99
|
+
tuples = super
|
100
|
+
return tuples if tuples.kind_of?(Array) # in case of several tuples just return the tuples as they are
|
101
|
+
#tuples.reload2 # reload2 is defined in lib/activerecord_ext.rb
|
102
|
+
tuples.class.where(tuples.class[:id].eq(tuples.id))[0] # in case of only one tuple return a reloaded tuple based on the class of this tuple
|
103
|
+
# this imply a "full" load of the tuple
|
104
|
+
# A VOIR AVEC LB peut être préfère t il laisser reload2
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def self.delete_all #contrary to destroy_all this is useful to override this method : In fact destroy_all will explicitly call a destroy method on each object
|
109
|
+
#whereas delete_all doesn't and only call a specific SQL request
|
110
|
+
# (to be even more precise delete explictly call delete_all with special conditions )
|
111
|
+
|
112
|
+
self.all.each{|o| o.delete } #call delete method for each instance of the class
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
send :include, InstanceMethods
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
#------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
134
|
+
#------------------------------------------------------------------------------------------------------------------------
|
135
|
+
#
|
136
|
+
# methods that will be used for the instances of the Non Mother Classes
|
137
|
+
#
|
138
|
+
#------------------------------------------------------------------------------------------------------------------------
|
139
|
+
|
140
|
+
module InstanceMethods1
|
141
|
+
|
142
|
+
def save
|
143
|
+
|
144
|
+
|
145
|
+
attributes_for_super = self.attributes.select{|key,value| self.class.superclass.column_names.include?(key) } #get the attributes of the class of the instance that also belong to its superclass
|
146
|
+
attributes_for_part_of = self.attributes.select{|key,value| !self.class.superclass.column_names.include?(key) } #get the attributes of the class of the instance that do not belong to its superclass
|
147
|
+
# these pieces of information should be stored in the table associated to the class of the instance
|
148
|
+
herited = self.class.superclass.new(attributes_for_super) #create a new instance of the superclass of the considered instance (self)
|
149
|
+
if(!new_record?)
|
150
|
+
herited.swap_new_record
|
151
|
+
herited.id = self.id
|
152
|
+
end
|
153
|
+
|
154
|
+
if(herited.class==herited.class.mother_class)
|
155
|
+
herited_saved = herited.save # save the new instance (by calling its save method)
|
156
|
+
else
|
157
|
+
herited_saved = herited.saveBis # save the new instance (by calling its save method)
|
158
|
+
end
|
159
|
+
|
160
|
+
if(herited_saved==false)
|
161
|
+
alert('please contact us') # que faire si herited_saved vaut false ? A VOIR
|
162
|
+
end
|
163
|
+
|
164
|
+
part_of_saved=true
|
165
|
+
if( ! attributes_for_part_of.empty? ) #if there are some pieces of information to save in the table associated to the class of the considered instance
|
166
|
+
part_of = self.class::PartOf.new(attributes_for_part_of)
|
167
|
+
part_of.id = herited.id
|
168
|
+
|
169
|
+
if(!new_record?)
|
170
|
+
part_of.swap_new_record
|
171
|
+
end
|
172
|
+
|
173
|
+
part_of_saved = part_of.save
|
174
|
+
if(part_of_saved==false)
|
175
|
+
alert('please contact us...') # que faire si herited_saved vaut false ? A VOIR
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
|
180
|
+
self.id = herited.id
|
181
|
+
|
182
|
+
sql = "UPDATE #{self.class.mother_class.table_name} SET #{self.class.inheritance_column} = '#{self.class.to_s}' WHERE id = #{self.id}"
|
183
|
+
if RAILS_ENV == 'development'
|
184
|
+
puts "SQL : #{sql}"
|
185
|
+
end
|
186
|
+
self.connection.execute(sql)
|
187
|
+
return herited_saved && part_of_saved
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
def saveBis
|
193
|
+
|
194
|
+
|
195
|
+
attributes_for_super = self.attributes.select{|key,value| self.class.superclass.column_names.include?(key) } #get the attributes of the class of the instance that also belong to its superclass
|
196
|
+
attributes_for_part_of = self.attributes.select{|key,value| !self.class.superclass.column_names.include?(key) } #get the attributes of the class of the instance that do not belong to its superclass
|
197
|
+
# these pieces of information should be stored in the table associated to the class of the instance
|
198
|
+
herited = self.class.superclass.new(attributes_for_super) #create a new instance of the superclass of the considered instance (self)
|
199
|
+
if(!new_record?)
|
200
|
+
herited.swap_new_record
|
201
|
+
herited.id = self.id
|
202
|
+
end
|
203
|
+
|
204
|
+
|
205
|
+
if(herited.class==herited.class.mother_class)
|
206
|
+
herited_saved = herited.save # save the new instance (by calling its save method)
|
207
|
+
else
|
208
|
+
herited_saved = herited.saveBis # save the new instance (by calling its save method)
|
209
|
+
end
|
210
|
+
|
211
|
+
if(herited_saved==false)
|
212
|
+
alert('please contact altrabio use the following mail : altrabio...altrabio.com') # que faire si herited_saved vaut false ? A VOIR
|
213
|
+
end
|
214
|
+
|
215
|
+
part_of_saved=true
|
216
|
+
if( ! attributes_for_part_of.empty? ) #if there are some piecesof information to save in the table associated to the class of the cosidered instance
|
217
|
+
part_of = self.class::PartOf.new(attributes_for_part_of) #
|
218
|
+
part_of.id = herited.id
|
219
|
+
|
220
|
+
if(!new_record?)
|
221
|
+
part_of.swap_new_record
|
222
|
+
end
|
223
|
+
|
224
|
+
part_of_saved = part_of.save
|
225
|
+
if(part_of_saved==false)
|
226
|
+
alert('please contact altrabio use the following mail : altrabio...altrabio.com') # que faire si herited_saved vaut false ? A VOIR
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
|
231
|
+
self.id = herited.id
|
232
|
+
|
233
|
+
return herited_saved && part_of_saved
|
234
|
+
end
|
235
|
+
|
236
|
+
def delete #call the class delete method with the id of the instance
|
237
|
+
if RAILS_ENV == 'development'
|
238
|
+
puts("1-> delete d'instance #{self.id} la classe est #{self.class.name}")
|
239
|
+
end
|
240
|
+
self.class.delete( self.id)
|
241
|
+
|
242
|
+
if RAILS_ENV == 'development'
|
243
|
+
puts("wl1")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
|
251
|
+
|
252
|
+
|
253
|
+
|
254
|
+
|
255
|
+
|
256
|
+
|
257
|
+
|
258
|
+
#------------------------------------------------------------------------------------------------------------------------
|
259
|
+
#
|
260
|
+
# methods that will be used for the instances of the Mother Class
|
261
|
+
#
|
262
|
+
#------------------------------------------------------------------------------------------------------------------------
|
263
|
+
|
264
|
+
module InstanceMethods
|
265
|
+
|
266
|
+
|
267
|
+
def updatetype
|
268
|
+
sql = "UPDATE #{self.class.mother_class.table_name} SET #{self.class.inheritance_column} = '#{self.class.to_s}' WHERE id = #{self.id}"
|
269
|
+
self.connection.execute(sql)
|
270
|
+
puts"#{sql}"
|
271
|
+
end
|
272
|
+
|
273
|
+
def destroy
|
274
|
+
super
|
275
|
+
if self.class.respond_to?('has_a_part_of?')
|
276
|
+
qdestroy
|
277
|
+
else
|
278
|
+
return self
|
279
|
+
end
|
280
|
+
end
|
281
|
+
|
282
|
+
def qdestroy
|
283
|
+
xxx=self.class
|
284
|
+
qqq=xxx
|
285
|
+
|
286
|
+
while xxx!=ActiveRecord::Base do
|
287
|
+
|
288
|
+
if xxx.respond_to?('has_a_part_of?') # eventually delete pieces of information stored in the write tables associated to the current xxx class for the object (if there is such a table)
|
289
|
+
|
290
|
+
if (xxx.superclass==xxx.mother_class || xxx::PartOf!=xxx.superclass::PartOf)
|
291
|
+
|
292
|
+
puts "partof for class = #{xxx.name}"
|
293
|
+
xxx::PartOf.destroy(self.id)
|
294
|
+
#oo=xxx::PartOf.find(self.id)
|
295
|
+
#oo.destroy
|
296
|
+
|
297
|
+
else
|
298
|
+
puts "no part of for class = #{xxx.name}"
|
299
|
+
end#partof
|
300
|
+
end #respond
|
301
|
+
|
302
|
+
qqq=xxx
|
303
|
+
xxx=xxx.superclass
|
304
|
+
|
305
|
+
end #while
|
306
|
+
|
307
|
+
puts "#{qqq.name} should be the mother class"
|
308
|
+
qqq.delete(self.id) #delete information into the table of the mother class
|
309
|
+
|
310
|
+
return self
|
311
|
+
end
|
312
|
+
|
313
|
+
|
314
|
+
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
|
319
|
+
|
320
|
+
|
321
|
+
|
322
|
+
end
|
323
|
+
ActiveRecord::Base.send :include, Cities
|
324
|
+
|
325
|
+
|
@@ -0,0 +1,282 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
#------------------------------------------------------------------------------------------------#
|
7
|
+
# #
|
8
|
+
# Modifications for ActiveRecord #
|
9
|
+
# #
|
10
|
+
#------------------------------------------------------------------------------------------------#
|
11
|
+
|
12
|
+
class ActiveRecord::Base
|
13
|
+
|
14
|
+
def reload
|
15
|
+
self.class.find(self.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.[](column_name)
|
19
|
+
arel_table[column_name]
|
20
|
+
end
|
21
|
+
|
22
|
+
def swap_new_record # a new own method to arbitrary change the value of the @persisted instance variable
|
23
|
+
# (this instance variable is a flag which indicates if a record is a new one or not)
|
24
|
+
@persisted=!@persisted
|
25
|
+
puts "not persisted"
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
def self.create_class_part_of(class_reference) #creation of a new class which inherits from ActiveRecord::Base
|
30
|
+
|
31
|
+
def class_reference.has_a_part_of?
|
32
|
+
return true
|
33
|
+
end
|
34
|
+
|
35
|
+
Class.new(ActiveRecord::Base) do
|
36
|
+
a=class_reference.table_name
|
37
|
+
b=a[5..a.length]
|
38
|
+
set_table_name(b)#set the name of the table associated to this class
|
39
|
+
# this class will be associated to the write table of the class_reference class
|
40
|
+
# consequently the name of the table is the name of the read table without "view_"
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
#------------------------------------------------------------------------------------------------#
|
56
|
+
# #
|
57
|
+
# Modifications for ActiveRecord::Persistence #
|
58
|
+
# #
|
59
|
+
#------------------------------------------------------------------------------------------------#
|
60
|
+
|
61
|
+
module ActiveRecord
|
62
|
+
|
63
|
+
module Persistence
|
64
|
+
|
65
|
+
def destroy
|
66
|
+
|
67
|
+
if persisted?
|
68
|
+
if (self.class.respond_to?("mother_class"))&&(self.class.table_name[0]=="v" && self.class.table_name[1]=="i" && self.class.table_name[2]=="e" && self.class.table_name[3]=="w" && self.class.table_name[4]=="_")
|
69
|
+
#if the class of the object is based on this gem and if the considered table is a view
|
70
|
+
puts"modified version of ActiveRecord::Persistence destroy"
|
71
|
+
puts "class = #{self.class.name} table name=#{self.class.table_name} this is a view : skipping some instructions"
|
72
|
+
else
|
73
|
+
puts"unmodified version of ActiveRecord::Persistence destroy"
|
74
|
+
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).delete_all
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
@destroyed = true
|
79
|
+
|
80
|
+
freeze
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
#-----------------------------------------------------------------------------------------------#
|
90
|
+
# #
|
91
|
+
# Some functions to manage views creation & dropping #
|
92
|
+
# #
|
93
|
+
#-----------------------------------------------------------------------------------------------#
|
94
|
+
def CreateTheViewForCITIEs(theclass) #function for creating views for migrations
|
95
|
+
|
96
|
+
if RAILS_ENV == 'development'
|
97
|
+
puts "CreateTheView 1"
|
98
|
+
end
|
99
|
+
self_columns = theclass::PartOf.column_names.select{ |c| c != "id" }
|
100
|
+
if RAILS_ENV == 'development'
|
101
|
+
puts "CreateTheView 2"
|
102
|
+
end
|
103
|
+
parent_columns = theclass.superclass.column_names.select{ |c| c != "id" }
|
104
|
+
columns = parent_columns+self_columns
|
105
|
+
if RAILS_ENV == 'development'
|
106
|
+
puts "CreateTheView 3"
|
107
|
+
end
|
108
|
+
self_read_table = theclass.table_name
|
109
|
+
# eventuellement warning si pas de part_of
|
110
|
+
self_write_table = theclass::PartOf.table_name
|
111
|
+
parent_read_table = theclass.superclass.table_name
|
112
|
+
if RAILS_ENV == 'development'
|
113
|
+
puts "CreateTheView 4"
|
114
|
+
end
|
115
|
+
|
116
|
+
if RAILS_ENV == 'development'
|
117
|
+
puts " self read table #{self_read_table} | parent_read_table #{parent_read_table}"
|
118
|
+
end
|
119
|
+
sql = "CREATE VIEW #{self_read_table} AS SELECT #{parent_read_table}.id, #{columns.join(',')} FROM #{parent_read_table}, #{self_write_table} WHERE #{parent_read_table}.id = #{self_write_table}.id"
|
120
|
+
theclass.connection.execute sql
|
121
|
+
end
|
122
|
+
|
123
|
+
def DropTheViewForCITIEs(theclass) #function for dropping views for migrations
|
124
|
+
if RAILS_ENV == 'development'
|
125
|
+
puts "1 DropTheViewForCITIEs"
|
126
|
+
end
|
127
|
+
self_read_table = theclass.table_name
|
128
|
+
|
129
|
+
if RAILS_ENV == 'development'
|
130
|
+
puts " DROP VIEW #{self_read_table}"
|
131
|
+
end
|
132
|
+
sql = "DROP VIEW #{self_read_table}"
|
133
|
+
theclass.connection.execute sql
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
#------------------------------------------------------------------------------------------------#
|
138
|
+
# #
|
139
|
+
# Modifications for SQL Adapters : needed to take views into account #
|
140
|
+
# (only SQLite, PostGreSQL & MySQL has been considered) #
|
141
|
+
# #
|
142
|
+
#------------------------------------------------------------------------------------------------#
|
143
|
+
|
144
|
+
|
145
|
+
#------------------------------------------------------------------------------------------------#
|
146
|
+
# Modifications for SQL Adapters : SQLite #
|
147
|
+
#------------------------------------------------------------------------------------------------#
|
148
|
+
require 'active_record'
|
149
|
+
require 'active_record/connection_adapters/sqlite_adapter'
|
150
|
+
require 'active_record/connection_adapters/sqlite3_adapter'
|
151
|
+
require 'active_record/connection_adapters/postgresql_adapter'
|
152
|
+
module ActiveRecord
|
153
|
+
module ConnectionAdapters
|
154
|
+
class SQLiteAdapter < AbstractAdapter
|
155
|
+
|
156
|
+
def tables(name = nil)
|
157
|
+
sql = <<-SQL
|
158
|
+
SELECT name
|
159
|
+
FROM sqlite_master
|
160
|
+
WHERE (type = 'table' or type='view') AND NOT name = 'sqlite_sequence'
|
161
|
+
SQL
|
162
|
+
# Modification : the where clause was intially WHERE type = 'table' AND NOT name = 'sqlite_sequence'
|
163
|
+
# now it is WHERE (type = 'table' or type='view') AND NOT name = 'sqlite_sequence'
|
164
|
+
# this modification is made to consider tables AND VIEWS as tables
|
165
|
+
|
166
|
+
execute(sql, name).map do |row|
|
167
|
+
row['name']
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
|
175
|
+
|
176
|
+
#------------------------------------------------------------------------------------------------#
|
177
|
+
# Modifications for SQL Adapters : PostGreSQL #
|
178
|
+
#------------------------------------------------------------------------------------------------#
|
179
|
+
|
180
|
+
|
181
|
+
module ActiveRecord
|
182
|
+
module ConnectionAdapters
|
183
|
+
class PostgreSQLAdapter < AbstractAdapter
|
184
|
+
def tables(name = nil)
|
185
|
+
a=tablesL(name)
|
186
|
+
puts("1------>#{a}")
|
187
|
+
b=viewsL(name)
|
188
|
+
if(b!=[])
|
189
|
+
a=a+b
|
190
|
+
end
|
191
|
+
puts("2------>#{a}")
|
192
|
+
return a
|
193
|
+
end
|
194
|
+
|
195
|
+
def tablesL(name = nil)
|
196
|
+
|
197
|
+
query(<<-SQL, name).map { |row| row[0] }
|
198
|
+
SELECT tablename
|
199
|
+
FROM pg_tables
|
200
|
+
WHERE schemaname = ANY (current_schemas(false))
|
201
|
+
SQL
|
202
|
+
end
|
203
|
+
def viewsL(name = nil)
|
204
|
+
|
205
|
+
query(<<-SQL, name).map { |row| row[0] }
|
206
|
+
SELECT viewname
|
207
|
+
FROM pg_views
|
208
|
+
WHERE schemaname = ANY (current_schemas(false))
|
209
|
+
SQL
|
210
|
+
end
|
211
|
+
|
212
|
+
def table_exists?(name)
|
213
|
+
a=table_existsB?(name)
|
214
|
+
b=views_existsB?(name)
|
215
|
+
puts"T---->#{a}"
|
216
|
+
puts"T---->#{b}"
|
217
|
+
return a||b
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
def table_existsB?(name)
|
222
|
+
name = name.to_s
|
223
|
+
schema, table = name.split('.', 2)
|
224
|
+
|
225
|
+
unless table # A table was provided without a schema
|
226
|
+
table = schema
|
227
|
+
schema = nil
|
228
|
+
end
|
229
|
+
|
230
|
+
if name =~ /^"/ # Handle quoted table names
|
231
|
+
table = name
|
232
|
+
schema = nil
|
233
|
+
end
|
234
|
+
|
235
|
+
query(<<-SQL).first[0].to_i > 0
|
236
|
+
SELECT COUNT(*)
|
237
|
+
FROM pg_tables
|
238
|
+
WHERE tablename = '#{table.gsub(/(^"|"$)/,'')}'
|
239
|
+
#{schema ? "AND schemaname = '#{schema}'" : ''}
|
240
|
+
SQL
|
241
|
+
|
242
|
+
end
|
243
|
+
def views_existsB?(name)
|
244
|
+
name = name.to_s
|
245
|
+
schema, table = name.split('.', 2)
|
246
|
+
|
247
|
+
unless table # A table was provided without a schema
|
248
|
+
table = schema
|
249
|
+
schema = nil
|
250
|
+
end
|
251
|
+
|
252
|
+
if name =~ /^"/ # Handle quoted table names
|
253
|
+
table = name
|
254
|
+
schema = nil
|
255
|
+
end
|
256
|
+
|
257
|
+
query(<<-SQL).first[0].to_i > 0
|
258
|
+
SELECT COUNT(*)
|
259
|
+
FROM pg_views
|
260
|
+
WHERE viewname = '#{table.gsub(/(^"|"$)/,'')}'
|
261
|
+
#{schema ? "AND schemaname = '#{schema}'" : ''}
|
262
|
+
SQL
|
263
|
+
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
|
271
|
+
#------------------------------------------------------------------------------------------------#
|
272
|
+
# Modifications for SQL Adapters : MySQL #
|
273
|
+
#------------------------------------------------------------------------------------------------#
|
274
|
+
|
275
|
+
# No Modification needed, this essentially comes from the fact that MySQL "show" command
|
276
|
+
# lists simultaneously tables & views
|
277
|
+
|
278
|
+
|
279
|
+
|
280
|
+
|
281
|
+
|
282
|
+
# ------------------------------------------------------------- #
|
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: CITIEsForRAILS
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Laurent Buffat & Pierre-Emmanuel JOUVE
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-15 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: |-
|
22
|
+
CITIEsForRAILS (Class Inheritance & Table Iheritance Embeddings For RAILS) is a solution that extends Single/Multiple/Class Table Inheritance. This solution is based on classical Ruby class inheritance, single table inheritance as well as DB views.
|
23
|
+
|
24
|
+
|
25
|
+
For Full Information GO TO : http://altrabio.github.com/CITIEsForRAILS/
|
26
|
+
email: citiesforrails @nospam@ gmail.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- lib/citiesforrails.rb
|
33
|
+
- lib/citiesforrails/acts_as_cities.rb
|
34
|
+
- lib/citiesforrails/core_ext.rb
|
35
|
+
files:
|
36
|
+
- Rakefile
|
37
|
+
- lib/citiesforrails.rb
|
38
|
+
- lib/citiesforrails/acts_as_cities.rb
|
39
|
+
- lib/citiesforrails/core_ext.rb
|
40
|
+
- Manifest
|
41
|
+
- CITIEsForRAILS.gemspec
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: https://github.com/altrabio/CITIEsForRAILS
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --line-numbers
|
49
|
+
- --inline-source
|
50
|
+
- --title
|
51
|
+
- CITIEsForRAILS
|
52
|
+
- --main
|
53
|
+
- README
|
54
|
+
require_paths:
|
55
|
+
- lib
|
56
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 1
|
71
|
+
- 2
|
72
|
+
version: "1.2"
|
73
|
+
requirements: []
|
74
|
+
|
75
|
+
rubyforge_project: citiesforrails
|
76
|
+
rubygems_version: 1.3.7
|
77
|
+
signing_key:
|
78
|
+
specification_version: 3
|
79
|
+
summary: "CITIEsForRAILS (Class Inheritance & Table Iheritance Embeddings For RAILS) is a solution that extends Single/Multiple/Class Table Inheritance. This solution is based on classical Ruby class inheritance, single table inheritance as well as DB views. For Full Information GO TO : http://altrabio.github.com/CITIEsForRAILS/"
|
80
|
+
test_files: []
|
81
|
+
|