rdl 1.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/rails_types.rb +1 -0
- data/lib/rdl.rb +56 -0
- data/lib/rdl/config.rb +121 -0
- data/lib/rdl/contracts/and.rb +29 -0
- data/lib/rdl/contracts/contract.rb +7 -0
- data/lib/rdl/contracts/flat.rb +31 -0
- data/lib/rdl/contracts/or.rb +25 -0
- data/lib/rdl/contracts/proc.rb +24 -0
- data/lib/rdl/switch.rb +20 -0
- data/lib/rdl/types/annotated_arg.rb +41 -0
- data/lib/rdl/types/finitehash.rb +81 -0
- data/lib/rdl/types/generic.rb +100 -0
- data/lib/rdl/types/intersection.rb +66 -0
- data/lib/rdl/types/lexer.rex +39 -0
- data/lib/rdl/types/lexer.rex.rb +148 -0
- data/lib/rdl/types/method.rb +219 -0
- data/lib/rdl/types/nil.rb +50 -0
- data/lib/rdl/types/nominal.rb +80 -0
- data/lib/rdl/types/optional.rb +54 -0
- data/lib/rdl/types/parser.racc +150 -0
- data/lib/rdl/types/parser.tab.rb +654 -0
- data/lib/rdl/types/singleton.rb +62 -0
- data/lib/rdl/types/structural.rb +72 -0
- data/lib/rdl/types/top.rb +50 -0
- data/lib/rdl/types/tuple.rb +61 -0
- data/lib/rdl/types/type.rb +24 -0
- data/lib/rdl/types/type_inferencer.rb +73 -0
- data/lib/rdl/types/union.rb +74 -0
- data/lib/rdl/types/var.rb +51 -0
- data/lib/rdl/types/vararg.rb +54 -0
- data/lib/rdl/types/wild.rb +26 -0
- data/lib/rdl/util.rb +56 -0
- data/lib/rdl/wrap.rb +505 -0
- data/lib/rdl_types.rb +2 -0
- data/types/other/chronic.rb +5 -0
- data/types/other/paperclip_attachment.rb +7 -0
- data/types/other/securerandom.rb +4 -0
- data/types/rails-4.2.1/fixnum.rb +3 -0
- data/types/rails-4.2.1/string.rb +3 -0
- data/types/rails-tmp/action_dispatch.rb +406 -0
- data/types/rails-tmp/active_record.rb +406 -0
- data/types/rails-tmp/devise_contracts.rb +216 -0
- data/types/ruby-2.2.0/_aliases.rb +4 -0
- data/types/ruby-2.2.0/abbrev.rb +5 -0
- data/types/ruby-2.2.0/array.rb +137 -0
- data/types/ruby-2.2.0/base64.rb +10 -0
- data/types/ruby-2.2.0/basic_object.rb +13 -0
- data/types/ruby-2.2.0/benchmark.rb +11 -0
- data/types/ruby-2.2.0/bigdecimal.rb +15 -0
- data/types/ruby-2.2.0/bigmath.rb +12 -0
- data/types/ruby-2.2.0/class.rb +17 -0
- data/types/ruby-2.2.0/complex.rb +42 -0
- data/types/ruby-2.2.0/coverage.rb +6 -0
- data/types/ruby-2.2.0/csv.rb +5 -0
- data/types/ruby-2.2.0/date.rb +6 -0
- data/types/ruby-2.2.0/dir.rb +38 -0
- data/types/ruby-2.2.0/encoding.rb +23 -0
- data/types/ruby-2.2.0/enumerable.rb +98 -0
- data/types/ruby-2.2.0/enumerator.rb +26 -0
- data/types/ruby-2.2.0/exception.rb +15 -0
- data/types/ruby-2.2.0/file.rb +124 -0
- data/types/ruby-2.2.0/fileutils.rb +6 -0
- data/types/ruby-2.2.0/fixnum.rb +45 -0
- data/types/ruby-2.2.0/float.rb +54 -0
- data/types/ruby-2.2.0/gem.rb +245 -0
- data/types/ruby-2.2.0/hash.rb +72 -0
- data/types/ruby-2.2.0/integer.rb +31 -0
- data/types/ruby-2.2.0/io.rb +103 -0
- data/types/ruby-2.2.0/kernel.rb +89 -0
- data/types/ruby-2.2.0/marshal.rb +5 -0
- data/types/ruby-2.2.0/matchdata.rb +26 -0
- data/types/ruby-2.2.0/math.rb +53 -0
- data/types/ruby-2.2.0/numeric.rb +46 -0
- data/types/ruby-2.2.0/object.rb +73 -0
- data/types/ruby-2.2.0/pathname.rb +106 -0
- data/types/ruby-2.2.0/process.rb +127 -0
- data/types/ruby-2.2.0/random.rb +15 -0
- data/types/ruby-2.2.0/range.rb +38 -0
- data/types/ruby-2.2.0/rational.rb +31 -0
- data/types/ruby-2.2.0/regexp.rb +30 -0
- data/types/ruby-2.2.0/set.rb +58 -0
- data/types/ruby-2.2.0/string.rb +145 -0
- data/types/ruby-2.2.0/strscan.rb +7 -0
- data/types/ruby-2.2.0/symbol.rb +29 -0
- data/types/ruby-2.2.0/time.rb +68 -0
- data/types/ruby-2.2.0/uri.rb +18 -0
- data/types/ruby-2.2.0/yaml.rb +5 -0
- metadata +131 -0
data/lib/rdl_types.rb
ADDED
@@ -0,0 +1,406 @@
|
|
1
|
+
module RailsHelper
|
2
|
+
class << self
|
3
|
+
attr_accessor :namespace
|
4
|
+
attr_accessor :resources_stack
|
5
|
+
attr_accessor :inside_member
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.get_path_helper(name)
|
9
|
+
stack = RailsHelper.resources_stack.map {|e| e.to_s.singularize}
|
10
|
+
resources_str = stack.join("_")
|
11
|
+
method_prefix = resources_str == "" ? "#{name}" : "#{name}_#{resources_str}"
|
12
|
+
:"#{method_prefix}_path"
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_resource_info(controller, action)
|
16
|
+
controller_s = controller.singularize
|
17
|
+
controller_c = controller_s.camelize
|
18
|
+
|
19
|
+
case action
|
20
|
+
when :new
|
21
|
+
v = [/^GET$/]
|
22
|
+
p = "/#{controller_s}/new"
|
23
|
+
prefix = "#{controller_s}"
|
24
|
+
pht = "() -> String"
|
25
|
+
when :create
|
26
|
+
v = [/^POST$/]
|
27
|
+
p = "/#{controller_s}"
|
28
|
+
prefix = "#{controller_s}"
|
29
|
+
pht = "() -> String"
|
30
|
+
when :show
|
31
|
+
v = [/^GET$/]
|
32
|
+
p = "/#{controller_s}"
|
33
|
+
prefix = "#{controller_s}"
|
34
|
+
pht = "() -> String"
|
35
|
+
when :edit
|
36
|
+
v = [/^GET$/]
|
37
|
+
p = "/#{controller_s}/edit"
|
38
|
+
prefix = "edit_#{controller_s}"
|
39
|
+
pht = "() -> String"
|
40
|
+
when :update
|
41
|
+
v = [/^PUT$/, /^PATCH$/]
|
42
|
+
p = "/#{controller_s}"
|
43
|
+
prefix = "#{controller_s}"
|
44
|
+
pht = "() -> String"
|
45
|
+
when :destroy
|
46
|
+
v = [/^DELETE$/]
|
47
|
+
p = "/#{controller_s}"
|
48
|
+
prefix = "#{controller_s}"
|
49
|
+
pht = "() -> String"
|
50
|
+
else
|
51
|
+
raise Exception, "invalid action #{action.inspect}"
|
52
|
+
end
|
53
|
+
|
54
|
+
ph = "#{prefix}_path".to_sym
|
55
|
+
uh = "#{prefix}_url".to_sym
|
56
|
+
uht = pht
|
57
|
+
{:verb => v, :path => p, :path_helper => [ph, pht], :url_helper => [uh, uht]}
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.get_resources_info(controller, action)
|
61
|
+
controller_s = controller.singularize
|
62
|
+
controller_c = controller_s.camelize
|
63
|
+
n = RailsHelper.namespace.to_s
|
64
|
+
nnh = (n == "" ? "" : "#{n}_")
|
65
|
+
|
66
|
+
case action
|
67
|
+
when :index
|
68
|
+
v = [/^GET$/]
|
69
|
+
p = "/#{controller}"
|
70
|
+
prefix = "#{nnh}#{controller}"
|
71
|
+
pht = "() -> String"
|
72
|
+
when :new
|
73
|
+
v = [/^GET$/]
|
74
|
+
p = "/#{controller}/new"
|
75
|
+
|
76
|
+
if n == ""
|
77
|
+
prefix = "#{controller_s}"
|
78
|
+
else
|
79
|
+
prefix = "new_#{nnh}#{controller_s}"
|
80
|
+
end
|
81
|
+
|
82
|
+
pht = "() -> String"
|
83
|
+
when :create
|
84
|
+
v = [/^POST$/]
|
85
|
+
p = "/#{controller}"
|
86
|
+
prefix = "#{nnh}#{controller}"
|
87
|
+
pht = "() -> String"
|
88
|
+
when :show
|
89
|
+
v = [/^GET$/]
|
90
|
+
p = "/#{controller}/:id"
|
91
|
+
prefix = "#{nnh}#{controller_s}"
|
92
|
+
pht = "(#{controller_c}) -> String"
|
93
|
+
when :edit
|
94
|
+
v = [/^GET$/]
|
95
|
+
p = "/#{controller}/:id/edit"
|
96
|
+
prefix = "edit_#{nnh}#{controller_s}"
|
97
|
+
pht = "(#{controller_c}) -> String"
|
98
|
+
when :update
|
99
|
+
v = [/^PUT$/, /^PATCH$/]
|
100
|
+
p = "/#{controller}/:id"
|
101
|
+
prefix = "#{nnh}#{controller_s}"
|
102
|
+
pht = "(#{controller_c}) -> String"
|
103
|
+
when :destroy
|
104
|
+
v = [/^DELETE$/]
|
105
|
+
p = "/#{controller}/:id"
|
106
|
+
prefix = "#{nnh}#{controller_s}"
|
107
|
+
pht = "(#{controller_c}) -> String"
|
108
|
+
else
|
109
|
+
raise Exception, "invalid action #{action.inspect}"
|
110
|
+
end
|
111
|
+
|
112
|
+
p = "/#{nnh[0..-2]}#{p}" if nnh != ""
|
113
|
+
|
114
|
+
ph = "#{prefix}_path".to_sym
|
115
|
+
uh = "#{prefix}_url".to_sym
|
116
|
+
uht = pht
|
117
|
+
{:verb => v, :path => p, :path_helper => [ph, pht], :url_helper => [uh, uht]}
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.resource_routes_info_valid?(routes, controller, action, options={})
|
121
|
+
info = get_resource_info(controller, action)
|
122
|
+
r_p = info[:path]
|
123
|
+
r_v = info[:verb]
|
124
|
+
|
125
|
+
routes.any? {|r|
|
126
|
+
defaults = r.app.instance_variable_get(:@defaults)
|
127
|
+
path = r.path.spec.to_s.split('(')[0]
|
128
|
+
|
129
|
+
if defaults
|
130
|
+
defaults[:controller] == controller and defaults[:action] == action.to_s and path == r_p and r_v.include?(r.verb)
|
131
|
+
else
|
132
|
+
false
|
133
|
+
end
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.resources_routes_info_valid?(routes, controller, action, options={})
|
138
|
+
info = get_resources_info(controller, action)
|
139
|
+
r_p = info[:path]
|
140
|
+
r_v = info[:verb]
|
141
|
+
|
142
|
+
namespace = self.namespace.to_s
|
143
|
+
namespace == "" ? c2 = controller : c2 = "#{namespace}/#{controller}"
|
144
|
+
|
145
|
+
routes.any? {|r|
|
146
|
+
defaults = r.app.instance_variable_get(:@defaults)
|
147
|
+
path = r.path.spec.to_s.split('(')[0]
|
148
|
+
|
149
|
+
if defaults
|
150
|
+
defaults[:controller] == c2 and defaults[:action] == action.to_s and path == r_p and r_v.include?(r.verb)
|
151
|
+
else
|
152
|
+
false
|
153
|
+
end
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.resource_routes_valid?(routes, resources_args)
|
158
|
+
controller = resources_args[0].to_s.pluralize
|
159
|
+
controller_obj = controller.pluralize.camelize + "Controller"
|
160
|
+
controller_obj = eval(controller_obj)
|
161
|
+
options = resources_args[1].nil? ? {} : resources_args[1]
|
162
|
+
routes = Rails.application.routes.routes.to_a
|
163
|
+
|
164
|
+
actions = [:new, :create, :show, :edit, :update, :destroy]
|
165
|
+
|
166
|
+
if options.keys.include?(:only)
|
167
|
+
actions = options[:only]
|
168
|
+
elsif options.keys.include?(:except)
|
169
|
+
actions = actions - options[:except]
|
170
|
+
end
|
171
|
+
|
172
|
+
r1 = actions.all? {|action|
|
173
|
+
resource_routes_info_valid?(routes, controller, action, options)
|
174
|
+
}
|
175
|
+
|
176
|
+
r2 = actions.all? {|action|
|
177
|
+
info = get_resource_info(controller, action)
|
178
|
+
r_ph = info[:path_helper][0]
|
179
|
+
r_uh = info[:url_helper][0]
|
180
|
+
|
181
|
+
path_helper_added = controller_obj.instance_methods.include?(r_ph)
|
182
|
+
url_helper_added = controller_obj.instance_methods.include?(r_uh)
|
183
|
+
|
184
|
+
path_helper_added and url_helper_added
|
185
|
+
}
|
186
|
+
|
187
|
+
r1 and r2
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.resources_routes_valid?(routes, resources_args)
|
191
|
+
controller = resources_args[0].to_s
|
192
|
+
controller_obj = controller.camelize + "Controller"
|
193
|
+
controller_obj = eval(controller_obj)
|
194
|
+
options = resources_args[1].nil? ? {} : resources_args[1]
|
195
|
+
routes = Rails.application.routes.routes.to_a
|
196
|
+
|
197
|
+
actions = [:index, :new, :create, :show, :edit, :update, :destroy]
|
198
|
+
|
199
|
+
if options.keys.include?(:only)
|
200
|
+
actions = options[:only]
|
201
|
+
elsif options.keys.include?(:except)
|
202
|
+
actions = actions - options[:except]
|
203
|
+
end
|
204
|
+
|
205
|
+
r1 = actions.all? {|action|
|
206
|
+
resources_routes_info_valid?(routes, controller, action, options)
|
207
|
+
}
|
208
|
+
|
209
|
+
r2 = actions.all? {|action|
|
210
|
+
info = get_resources_info(controller, action)
|
211
|
+
r_ph = info[:path_helper][0]
|
212
|
+
r_uh = info[:url_helper][0]
|
213
|
+
|
214
|
+
path_helper_added = controller_obj.instance_methods.include?(r_ph)
|
215
|
+
url_helper_added = controller_obj.instance_methods.include?(r_uh)
|
216
|
+
|
217
|
+
path_helper_added and url_helper_added
|
218
|
+
}
|
219
|
+
|
220
|
+
r1 and r2
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
module ActionDispatch
|
225
|
+
module Routing
|
226
|
+
class Mapper
|
227
|
+
extend RDL
|
228
|
+
|
229
|
+
spec :root do
|
230
|
+
post_cond do |ret, *args|
|
231
|
+
methods = [:root_path, :root_url]
|
232
|
+
|
233
|
+
methods.all? {|m|
|
234
|
+
puts "ApplicationController ##% #{m} : () -> String"
|
235
|
+
|
236
|
+
#add_typesig(ApplicationController, m, "() -> String")
|
237
|
+
ApplicationController.instance_methods.include?(m)
|
238
|
+
}
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
spec :namespace do
|
243
|
+
pre_task do |*args, &blk|
|
244
|
+
RailsHelper.namespace = args[0]
|
245
|
+
end
|
246
|
+
|
247
|
+
post_task do |ret, *args, &blk|
|
248
|
+
RailsHelper.namespace = nil
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
spec :get do
|
253
|
+
pre_cond do |*args, &blk|
|
254
|
+
options = args[1] || {}
|
255
|
+
|
256
|
+
if options.keys.include?(:to)
|
257
|
+
if options[:to].class == String
|
258
|
+
controller = options[:to].split("#")[0]
|
259
|
+
controller = controller.camelize
|
260
|
+
action = options[:to].split("#")[1]
|
261
|
+
|
262
|
+
controller_defined = Object.const_defined?(controller)
|
263
|
+
|
264
|
+
# TODO: see if action was added. Need late binding?
|
265
|
+
|
266
|
+
controller_defined
|
267
|
+
else
|
268
|
+
true
|
269
|
+
end
|
270
|
+
else
|
271
|
+
true
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
post_cond do |ret, *args|
|
276
|
+
if RailsHelper.inside_member and not parent_resource.actions.include?(args[0])
|
277
|
+
path_helper = RailsHelper.get_path_helper(args[0])
|
278
|
+
ctrl = parent_resource.controller.singularize.camelize
|
279
|
+
|
280
|
+
puts "ApplicationController ##% #{path_helper} : (#{ctrl}) -> String"
|
281
|
+
|
282
|
+
add_typesig(ApplicationController, path_helper, "() -> String")
|
283
|
+
|
284
|
+
ApplicationController.instance_methods.include?(path_helper)
|
285
|
+
else
|
286
|
+
true
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
spec :post do
|
292
|
+
post_cond do |ret, *args|
|
293
|
+
if RailsHelper.inside_member and not parent_resource.actions.include?(args[0])
|
294
|
+
path_helper = RailsHelper.get_path_helper(args[0])
|
295
|
+
ctrl = parent_resource.controller.singularize.camelize
|
296
|
+
|
297
|
+
puts "ApplicationController ##% #{path_helper} : (#{ctrl}) -> String"
|
298
|
+
|
299
|
+
add_typesig(ApplicationController, path_helper, "() -> String")
|
300
|
+
|
301
|
+
ApplicationController.instance_methods.include?(path_helper)
|
302
|
+
else
|
303
|
+
true
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
spec :member do
|
309
|
+
pre_task do |*args|
|
310
|
+
RailsHelper.inside_member = true
|
311
|
+
end
|
312
|
+
|
313
|
+
post_task do |*args|
|
314
|
+
RailsHelper.inside_member = false
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
spec :resource do
|
319
|
+
post_task do |ret, *args, &blk|
|
320
|
+
return true if args[0] == :session or args[0] == :password or args[0] == :registration or args[0] == :confirmation
|
321
|
+
|
322
|
+
controller = args[0].to_s
|
323
|
+
controller_obj = controller.pluralize.camelize + "Controller"
|
324
|
+
controller_obj = eval(controller_obj)
|
325
|
+
options = args[1] || {}
|
326
|
+
routes = Rails.application.routes.routes.to_a
|
327
|
+
|
328
|
+
actions = [:new, :create, :show, :edit, :update, :destroy]
|
329
|
+
|
330
|
+
if options.keys.include?(:only)
|
331
|
+
actions = options[:only]
|
332
|
+
elsif options.keys.include?(:except)
|
333
|
+
actions = actions - options[:except]
|
334
|
+
end
|
335
|
+
|
336
|
+
actions.each {|action|
|
337
|
+
info = RailsHelper.get_resource_info(controller, action)
|
338
|
+
r_ph = info[:path_helper]
|
339
|
+
r_uh = info[:url_helper]
|
340
|
+
|
341
|
+
#typesig(controller_obj, r_ph[0], r_ph[1])
|
342
|
+
#typesig(controller_obj, r_uh[0], r_uh[1])
|
343
|
+
}
|
344
|
+
end
|
345
|
+
|
346
|
+
post_cond do |ret, *args, &blk|
|
347
|
+
return true if args[0] == :session or args[0] == :password or args[0] == :registration or args[0] == :confirmation
|
348
|
+
|
349
|
+
model = args[0].to_s
|
350
|
+
routes = Rails.application.routes.routes.to_a
|
351
|
+
|
352
|
+
new_routes_valid = RailsHelper.resource_routes_valid?(routes, args)
|
353
|
+
|
354
|
+
new_routes_valid
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
# TODO: resources arg can also be a list
|
359
|
+
spec :resources do
|
360
|
+
pre_task do |*args, &blk|
|
361
|
+
RailsHelper.resources_stack = [] if not RailsHelper.resources_stack
|
362
|
+
RailsHelper.resources_stack.push(args[0])
|
363
|
+
end
|
364
|
+
|
365
|
+
post_task do |ret, *args, &blk|
|
366
|
+
RailsHelper.resources_stack.pop
|
367
|
+
|
368
|
+
controller = args[0].to_s
|
369
|
+
controller_obj = controller.camelize + "Controller"
|
370
|
+
controller_obj = eval(controller_obj)
|
371
|
+
options = args[1] || {}
|
372
|
+
routes = Rails.application.routes.routes.to_a
|
373
|
+
|
374
|
+
actions = [:index, :new, :create, :show, :edit, :update, :destroy]
|
375
|
+
|
376
|
+
if options.keys.include?(:only)
|
377
|
+
actions = options[:only]
|
378
|
+
elsif options.keys.include?(:except)
|
379
|
+
actions = actions - options[:except]
|
380
|
+
end
|
381
|
+
|
382
|
+
actions.each {|action|
|
383
|
+
info = RailsHelper.get_resources_info(controller, action)
|
384
|
+
r_ph = info[:path_helper]
|
385
|
+
r_uh = info[:url_helper]
|
386
|
+
|
387
|
+
puts "#{controller_obj} ##% #{r_ph[0]} : #{r_ph[1]}"
|
388
|
+
puts "#{controller_obj} ##% #{r_uh[0]} : #{r_uh[1]}"
|
389
|
+
|
390
|
+
#typesig(controller_obj, r_ph[0], r_ph[1])
|
391
|
+
#typesig(controller_obj, r_uh[0], r_uh[1])
|
392
|
+
}
|
393
|
+
end
|
394
|
+
|
395
|
+
post_cond do |ret, *args, &blk|
|
396
|
+
model = args[0].to_s
|
397
|
+
routes = Rails.application.routes.routes.to_a
|
398
|
+
|
399
|
+
new_routes_valid = RailsHelper.resources_routes_valid?(routes, args)
|
400
|
+
|
401
|
+
new_routes_valid
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,406 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module Associations
|
3
|
+
module ClassMethods
|
4
|
+
extend RDL
|
5
|
+
|
6
|
+
def __rdl_get_arg_method_typesig(mname, arg_options)
|
7
|
+
if arg_options.keys.include?(:class_name)
|
8
|
+
c = arg_options[:class_name]
|
9
|
+
else
|
10
|
+
c = mname.to_s.singularize.camelize
|
11
|
+
end
|
12
|
+
|
13
|
+
t = "() -> Array<#{c}>"
|
14
|
+
|
15
|
+
puts "#{self} ##% #{mname} : #{t}"
|
16
|
+
|
17
|
+
t
|
18
|
+
end
|
19
|
+
|
20
|
+
def __rdl_option_keys_valid?(spec_valid_options, options_used)
|
21
|
+
# Original class association options can be found with
|
22
|
+
# ActiveRecord::Associations::Builder::Association.valid_options
|
23
|
+
# + some more found in ancestors.
|
24
|
+
|
25
|
+
common_options = [:class_name, :foreign_key, :select, :conditions, :include, :extend, :readonly, :validate, :autosave]
|
26
|
+
valid_options = common_options + spec_valid_options
|
27
|
+
options_used.keys.all? {|k| valid_options.include?(k)}
|
28
|
+
end
|
29
|
+
|
30
|
+
def __rdl_arg_objects_defined?(arg_name, arg_options)
|
31
|
+
if arg_options.keys.include?(:class_name)
|
32
|
+
n = arg_options[:class_name]
|
33
|
+
else
|
34
|
+
n = arg_name.to_s.singularize.camelize
|
35
|
+
end
|
36
|
+
|
37
|
+
r = true
|
38
|
+
|
39
|
+
if not (arg_options.keys.include?(:polymorphic) and arg_options[:polymorphic] == true)
|
40
|
+
begin
|
41
|
+
r = eval(n).ancestors.include?(ActiveRecord::Base)
|
42
|
+
rescue
|
43
|
+
r = false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
r
|
48
|
+
|
49
|
+
# TODO: Fix this, late binding?
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def __rdl_collection_methods_added?(collection, arg_options)
|
54
|
+
cstr = collection.to_s
|
55
|
+
cstr_s = cstr.singularize
|
56
|
+
new_self_methods = [cstr, "#{cstr}=", "#{cstr_s}_ids", "#{cstr_s}_ids="]
|
57
|
+
new_self_methods.map! {|m| m.to_sym}
|
58
|
+
|
59
|
+
# TODO: self.new is ok to call here, but may mutate global state in certain classes
|
60
|
+
# The class of self.new is Array here.
|
61
|
+
|
62
|
+
collection_obj = eval("#{self}.new.#{collection.to_s}")
|
63
|
+
|
64
|
+
new_collection_methods = [:push, :concat, :build, :create, :create!, :size, :length, :count, :sum, :empty?, :clear, :delete, :delete_all, :destroy_all, :find, :exists?, :uniq, :<<]
|
65
|
+
# TODO: reset is also defined on obj, according to the comment in associations.rb
|
66
|
+
# but collection_obj.respond(:reset) returns false
|
67
|
+
# However, http://guides.rubyonrails.org/association_basics.html does not list :reset
|
68
|
+
# as well as several methods from the above as auto-generated methods.
|
69
|
+
|
70
|
+
methods_added_on_self = new_self_methods.all? {|m|
|
71
|
+
self.instance_methods.include?(m)
|
72
|
+
}
|
73
|
+
|
74
|
+
methods_added_on_collection = new_collection_methods.all? {|m|
|
75
|
+
collection_obj.respond_to?(m)
|
76
|
+
}
|
77
|
+
|
78
|
+
methods_added_on_self and methods_added_on_collection
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
def __rdl_singular_methods_added?(type, assoc, arg_options)
|
83
|
+
new_methods = {}
|
84
|
+
|
85
|
+
if arg_options.keys.include?(:class_name)
|
86
|
+
cls = arg_options[:class_name]
|
87
|
+
else
|
88
|
+
cls = assoc.to_s.camelize
|
89
|
+
end
|
90
|
+
|
91
|
+
if type == :belongs_to
|
92
|
+
if arg_options.keys.include?(:polymorphic) and arg_options[:polymorphic] == true
|
93
|
+
new_methods[:"#{assoc}"] = "(?%bool) -> #{cls}"
|
94
|
+
new_methods[:"#{assoc}="] = "(#{cls}) -> #{cls}"
|
95
|
+
else
|
96
|
+
new_methods[:"#{assoc}"] = "(?%bool) -> #{cls}"
|
97
|
+
new_methods[:"#{assoc}="] = "(#{cls}) -> #{cls}"
|
98
|
+
new_methods[:"build_#{assoc}"] = "(Hash) -> #{cls}"
|
99
|
+
new_methods[:"create_#{assoc}"] = "(Hash) -> #{cls}"
|
100
|
+
new_methods[:"create_#{assoc}!"] = "(Hash) -> #{cls}"
|
101
|
+
end
|
102
|
+
elsif type == :has_one
|
103
|
+
new_methods[:"#{assoc}"] = "(?%bool) -> #{cls}"
|
104
|
+
new_methods[:"#{assoc}="] = "(#{cls}) -> #{cls}"
|
105
|
+
new_methods[:"build_#{assoc}"] = "(Hash) -> #{cls}"
|
106
|
+
new_methods[:"create_#{assoc}"] = "(Hash) -> #{cls}"
|
107
|
+
new_methods[:"create_#{assoc}!"] = "(Hash) -> #{cls}"
|
108
|
+
else
|
109
|
+
raise Exception, "type must be a singular association"
|
110
|
+
end
|
111
|
+
|
112
|
+
new_methods.each {|k, v|
|
113
|
+
puts "#{self} ##% #{k} : #{v}"
|
114
|
+
|
115
|
+
#add_typesig(self, k, v)
|
116
|
+
}
|
117
|
+
|
118
|
+
new_methods.keys.all? {|m| self.instance_methods.include?(m)}
|
119
|
+
end
|
120
|
+
|
121
|
+
spec :belongs_to do
|
122
|
+
pre_task do |*args|
|
123
|
+
$belongs_to_arg_name = args[0]
|
124
|
+
|
125
|
+
if args.size == 2
|
126
|
+
$belongs_to_arg_options = args[1].dup
|
127
|
+
else
|
128
|
+
$belongs_to_arg_options = {}
|
129
|
+
end
|
130
|
+
|
131
|
+
$belongs_to_self = self
|
132
|
+
end
|
133
|
+
|
134
|
+
pre_cond do |*args|
|
135
|
+
$belongs_to_arg_name = args[0]
|
136
|
+
arg_name = $belongs_to_arg_name
|
137
|
+
|
138
|
+
if args.size == 2
|
139
|
+
$belongs_to_arg_options = args[1].dup
|
140
|
+
else
|
141
|
+
$belongs_to_arg_options = {}
|
142
|
+
end
|
143
|
+
|
144
|
+
slf = eval("self")
|
145
|
+
arg_options = $belongs_to_arg_options
|
146
|
+
|
147
|
+
spec_valid_options = [:foreign_type, :polymorphic, :touch, :remote, :dependent, :counter_cache, :primary_key, :inverse_of]
|
148
|
+
option_keys_valid = __rdl_option_keys_valid?(spec_valid_options, arg_options)
|
149
|
+
arg_classes_defined = __rdl_arg_objects_defined?(arg_name, arg_options)
|
150
|
+
|
151
|
+
if arg_options.keys.include?(:foreign_key)
|
152
|
+
fk = arg_options[:foreign_key]
|
153
|
+
else
|
154
|
+
fk = "#{arg_name.to_s.underscore}_id"
|
155
|
+
end
|
156
|
+
|
157
|
+
col_names = slf.columns.map {|x| x.name}
|
158
|
+
foreign_key_col_exist = col_names.include?(fk)
|
159
|
+
|
160
|
+
counter_cache_col_exist = true
|
161
|
+
|
162
|
+
if (arg_options.keys.include?(:counter_cache) and arg_options[:counter_cache]) and not (arg_options.keys.include?(:polymorphic) and arg_options[:polymorphic])
|
163
|
+
if arg_options.keys.include?(:class_name)
|
164
|
+
assoc = arg_options[:class_name]
|
165
|
+
else
|
166
|
+
assoc = arg_name.to_s.singularize.camelize
|
167
|
+
end
|
168
|
+
|
169
|
+
assoc_cls = eval(assoc)
|
170
|
+
assoc_cols = assoc_cls.columns.map {|x| x.name}
|
171
|
+
|
172
|
+
# can specify a symbol to override default
|
173
|
+
if arg_options[:counter_cache] != true
|
174
|
+
cid = arg_options[:counter_cache]
|
175
|
+
else
|
176
|
+
cid = "#{slf.to_s.pluralize.camelize(:lower)}_count"
|
177
|
+
end
|
178
|
+
|
179
|
+
counter_cache_col_exist = assoc_cols.include?(cid.to_s)
|
180
|
+
end
|
181
|
+
|
182
|
+
option_keys_valid and
|
183
|
+
arg_classes_defined and
|
184
|
+
foreign_key_col_exist and
|
185
|
+
counter_cache_col_exist
|
186
|
+
end
|
187
|
+
|
188
|
+
post_cond do |ret, *args|
|
189
|
+
arg_name = $belongs_to_arg_name
|
190
|
+
arg_options = $belongs_to_arg_options
|
191
|
+
slf = $belongs_to_self
|
192
|
+
|
193
|
+
correct_methods_added = __rdl_singular_methods_added?(:belongs_to, arg_name, arg_options)
|
194
|
+
|
195
|
+
if arg_options.keys.include?(:foreign_key)
|
196
|
+
fk = arg_options[:foreign_key]
|
197
|
+
else
|
198
|
+
fk = "#{arg_name.to_s.underscore}_id"
|
199
|
+
end
|
200
|
+
|
201
|
+
foreign_key_added = (slf.reflections.keys.include?(arg_name) and
|
202
|
+
(slf.reflections[arg_name].foreign_key == fk))
|
203
|
+
|
204
|
+
arg_method_added = self.instance_methods.include?(args[0])
|
205
|
+
arg_method_typesig = __rdl_get_arg_method_typesig(args[0], arg_options)
|
206
|
+
|
207
|
+
puts "#{self} ##% #{args[0]} : #{arg_method_typesig}"
|
208
|
+
#add_typesig(self, args[0], arg_method_typesig)
|
209
|
+
|
210
|
+
arg_method_added and correct_methods_added and foreign_key_added
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
spec :has_one do
|
215
|
+
pre_task do |*args|
|
216
|
+
$has_to_arg_name = args[0]
|
217
|
+
|
218
|
+
if args.size == 2
|
219
|
+
$has_to_arg_options = args[1].dup
|
220
|
+
else
|
221
|
+
$has_to_arg_options = {}
|
222
|
+
end
|
223
|
+
|
224
|
+
$has_to_self = self
|
225
|
+
end
|
226
|
+
|
227
|
+
pre_cond do |*args|
|
228
|
+
$has_one_arg_name = args[0]
|
229
|
+
arg_name = $has_one_arg_name
|
230
|
+
|
231
|
+
if args.size == 2
|
232
|
+
$has_one_arg_options = args[1].dup
|
233
|
+
else
|
234
|
+
$has_one_arg_options = {}
|
235
|
+
end
|
236
|
+
|
237
|
+
slf = eval("self")
|
238
|
+
arg_options = $has_one_arg_options
|
239
|
+
|
240
|
+
spec_valid_options = [:order, :as, :through, :remote, :dependent, :counter_cache, :primary_key, :inverse_of]
|
241
|
+
option_keys_valid = __rdl_option_keys_valid?(spec_valid_options, arg_options)
|
242
|
+
arg_classes_defined = __rdl_arg_objects_defined?(arg_name, arg_options)
|
243
|
+
|
244
|
+
option_keys_valid and
|
245
|
+
arg_classes_defined
|
246
|
+
end
|
247
|
+
|
248
|
+
post_cond do |ret, *args|
|
249
|
+
arg_name = $has_one_arg_name
|
250
|
+
arg_options = $has_one_arg_options
|
251
|
+
slf = $has_one_self
|
252
|
+
|
253
|
+
correct_methods_added = __rdl_singular_methods_added?(:has_one, arg_name, arg_options)
|
254
|
+
|
255
|
+
arg_method_added = self.instance_methods.include?(args[0])
|
256
|
+
arg_method_typesig = __rdl_get_arg_method_typesig(args[0], arg_options)
|
257
|
+
|
258
|
+
puts "#{self} ##% #{args[0]} : #{arg_method_typesig}"
|
259
|
+
|
260
|
+
arg_method_added and correct_methods_added
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
spec :has_many do
|
265
|
+
pre_task do |*args|
|
266
|
+
$has_many_arg_name = args[0]
|
267
|
+
|
268
|
+
if args.size == 2
|
269
|
+
$has_many_arg_options = args[1].dup
|
270
|
+
else
|
271
|
+
$has_many_arg_options = {}
|
272
|
+
end
|
273
|
+
|
274
|
+
$has_many_self = self
|
275
|
+
end
|
276
|
+
|
277
|
+
pre_cond do |*args|
|
278
|
+
arg_name = args[0]
|
279
|
+
|
280
|
+
if args.size == 2
|
281
|
+
arg_options = args[1].dup
|
282
|
+
else
|
283
|
+
arg_options = {}
|
284
|
+
end
|
285
|
+
|
286
|
+
slf = eval("self")
|
287
|
+
|
288
|
+
spec_valid_options = [:primary_key, :dependent, :as, :through, :source, :source_type, :inverse_of, :table_name, :order, :group, :having, :limit, :offset, :uniq, :finder_sql, :counter_sql, :before_add, :after_add, :before_remove, :after_remove]
|
289
|
+
option_keys_valid = __rdl_option_keys_valid?(spec_valid_options, arg_options)
|
290
|
+
arg_classes_defined = __rdl_arg_objects_defined?(arg_name, arg_options)
|
291
|
+
|
292
|
+
option_keys_valid and
|
293
|
+
arg_classes_defined
|
294
|
+
end
|
295
|
+
|
296
|
+
post_cond do |ret, *args|
|
297
|
+
arg_name = $has_many_arg_name
|
298
|
+
arg_options = $has_many_arg_options
|
299
|
+
slf = $has_many_self
|
300
|
+
|
301
|
+
correct_methods_added = __rdl_collection_methods_added?(arg_name, arg_options)
|
302
|
+
|
303
|
+
if arg_options.keys.include?(:foreign_key)
|
304
|
+
fk = arg_options[:foreign_key]
|
305
|
+
elsif arg_options.keys.include?(:as)
|
306
|
+
fk = arg_options[:as].to_s + "_id"
|
307
|
+
elsif arg_options.keys.include?(:class_name)
|
308
|
+
fk = arg_options[:class_name].to_s.underscore.camelize(:lower) + "_id"
|
309
|
+
else
|
310
|
+
fk = "#{slf.to_s.camelize(:lower)}_id"
|
311
|
+
end
|
312
|
+
|
313
|
+
foreign_key_added = (slf.reflections.keys.include?(arg_name) and
|
314
|
+
(slf.reflections[arg_name].foreign_key == fk))
|
315
|
+
|
316
|
+
if arg_options.keys.include?(:foreign_key)
|
317
|
+
bad_fk = arg_options[:foreign_key]
|
318
|
+
else
|
319
|
+
bad_fk = "#{arg_name.to_s.underscore}_id"
|
320
|
+
end
|
321
|
+
|
322
|
+
col_names = slf.columns.map {|x| x.name}
|
323
|
+
bad_foreign_key_col_not_exist = (not col_names.include?(fk))
|
324
|
+
|
325
|
+
arg_method_added = self.instance_methods.include?(args[0])
|
326
|
+
arg_method_typesig = __rdl_get_arg_method_typesig(args[0], arg_options)
|
327
|
+
|
328
|
+
#add_typesig(self, args[0], arg_method_typesig)
|
329
|
+
|
330
|
+
puts "#{self} ##% #{args[0]} : #{arg_method_typesig}"
|
331
|
+
|
332
|
+
arg_method_added and
|
333
|
+
correct_methods_added and foreign_key_added and
|
334
|
+
bad_foreign_key_col_not_exist
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
spec :has_and_belongs_to_many do
|
339
|
+
pre_task do |*args|
|
340
|
+
$has_and_belongs_to_many_arg_name = args[0]
|
341
|
+
|
342
|
+
if args.size == 2
|
343
|
+
$has_and_belongs_to_many_arg_options = args[1].dup
|
344
|
+
else
|
345
|
+
$has_and_belongs_to_many_arg_options = {}
|
346
|
+
end
|
347
|
+
|
348
|
+
$has_and_belongs_to_many_self = self
|
349
|
+
end
|
350
|
+
|
351
|
+
pre_cond do |*args|
|
352
|
+
$has_and_belongs_to_many_arg_name = args[0]
|
353
|
+
arg_name = $has_and_belongs_to_many_arg_name
|
354
|
+
|
355
|
+
if args.size == 2
|
356
|
+
$has_and_belongs_to_many_arg_options = args[1].dup
|
357
|
+
else
|
358
|
+
$has_and_belongs_to_many_arg_options = {}
|
359
|
+
end
|
360
|
+
|
361
|
+
slf = eval("self")
|
362
|
+
arg_options = $has_and_belongs_to_many_arg_options
|
363
|
+
|
364
|
+
spec_valid_options = [:join_table, :association_foreign_key, :delete_sql, :insert_sql, :table_name, :order, :group, :having, :limit, :offset, :uniq, :finder_sql, :counter_sql, :before_add, :after_add, :before_remove, :after_remove]
|
365
|
+
option_keys_valid = __rdl_option_keys_valid?(spec_valid_options, arg_options)
|
366
|
+
|
367
|
+
arg_classes_defined = __rdl_arg_objects_defined?(arg_name, arg_options)
|
368
|
+
|
369
|
+
option_keys_valid and
|
370
|
+
arg_classes_defined
|
371
|
+
end
|
372
|
+
|
373
|
+
post_cond do |ret, *args|
|
374
|
+
arg_name = $has_and_belongs_to_many_arg_name
|
375
|
+
arg_options = $has_and_belongs_to_many_arg_options
|
376
|
+
slf = $has_and_belongs_to_many_self
|
377
|
+
|
378
|
+
correct_methods_added = __rdl_collection_methods_added?(arg_name, arg_options)
|
379
|
+
|
380
|
+
if arg_options.keys.include?(:foreign_key)
|
381
|
+
fk = arg_options[:foreign_key]
|
382
|
+
elsif arg_options.keys.include?(:as)
|
383
|
+
fk = arg_options[:as].to_s + "_id"
|
384
|
+
elsif arg_options.keys.include?(:class_name)
|
385
|
+
fk = arg_options[:class_name].to_s.underscore.camelize(:lower) + "_id"
|
386
|
+
else
|
387
|
+
fk = "#{slf.to_s.camelize(:lower)}_id"
|
388
|
+
end
|
389
|
+
|
390
|
+
arg_method_added = self.instance_methods.include?(args[0])
|
391
|
+
arg_method_typesig = __rdl_get_arg_method_typesig(args[0], arg_options)
|
392
|
+
|
393
|
+
# this adds methods like poster_lists, owned_lists, etc
|
394
|
+
#add_typesig(self, args[0], arg_method_typesig)
|
395
|
+
|
396
|
+
puts "#{self} ##% #{args[0]} : #{arg_method_typesig}"
|
397
|
+
|
398
|
+
foreign_key_added = (slf.reflections.keys.include?(arg_name) and
|
399
|
+
(slf.reflections[arg_name].foreign_key == fk))
|
400
|
+
|
401
|
+
arg_method_added and correct_methods_added and foreign_key_added
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|