rdl 2.0.0.rc2 → 2.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.md +7 -1
  3. data/README.md +94 -20
  4. data/lib/rdl.rb +4 -1
  5. data/lib/rdl/config.rb +90 -3
  6. data/lib/rdl/info.rb +16 -0
  7. data/lib/rdl/typecheck.rb +207 -79
  8. data/lib/rdl/types/bot.rb +1 -1
  9. data/lib/rdl/types/dependent_arg.rb +17 -8
  10. data/lib/rdl/types/{finitehash.rb → finite_hash.rb} +3 -29
  11. data/lib/rdl/types/generic.rb +1 -37
  12. data/lib/rdl/types/intersection.rb +1 -0
  13. data/lib/rdl/types/lexer.rex +2 -1
  14. data/lib/rdl/types/lexer.rex.rb +4 -1
  15. data/lib/rdl/types/method.rb +2 -12
  16. data/lib/rdl/types/nominal.rb +1 -22
  17. data/lib/rdl/types/non_null.rb +50 -0
  18. data/lib/rdl/types/parser.racc +3 -1
  19. data/lib/rdl/types/parser.tab.rb +222 -190
  20. data/lib/rdl/types/singleton.rb +1 -6
  21. data/lib/rdl/types/structural.rb +1 -10
  22. data/lib/rdl/types/top.rb +1 -2
  23. data/lib/rdl/types/tuple.rb +3 -19
  24. data/lib/rdl/types/type.rb +223 -0
  25. data/lib/rdl/types/union.rb +12 -2
  26. data/lib/rdl/types/var.rb +4 -1
  27. data/lib/rdl/types/wild_query.rb +1 -0
  28. data/lib/rdl/wrap.rb +199 -169
  29. data/lib/rdl_disable.rb +41 -0
  30. data/lib/rdl_types.rb +1 -4
  31. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/_aliases.rb +0 -0
  32. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/abbrev.rb +0 -0
  33. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/array.rb +56 -56
  34. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/base64.rb +0 -0
  35. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/basic_object.rb +0 -0
  36. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/benchmark.rb +0 -0
  37. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bigdecimal.rb +0 -0
  38. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bigmath.rb +0 -0
  39. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/bignum.rb +0 -0
  40. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/class.rb +0 -0
  41. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/complex.rb +0 -0
  42. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/coverage.rb +0 -0
  43. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/csv.rb +0 -0
  44. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/date.rb +0 -0
  45. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/dir.rb +0 -0
  46. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/encoding.rb +0 -0
  47. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/enumerable.rb +0 -0
  48. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/enumerator.rb +0 -0
  49. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/exception.rb +0 -0
  50. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/file.rb +0 -0
  51. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/fileutils.rb +0 -0
  52. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/fixnum.rb +0 -0
  53. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/float.rb +26 -26
  54. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/gem.rb +0 -0
  55. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/hash.rb +0 -0
  56. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/integer.rb +8 -8
  57. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/io.rb +0 -0
  58. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/kernel.rb +12 -11
  59. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/marshal.rb +0 -0
  60. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/matchdata.rb +0 -0
  61. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/math.rb +0 -0
  62. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/module.rb +0 -0
  63. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/nil.rb +0 -0
  64. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/numeric.rb +0 -0
  65. data/lib/types/core-ruby-2.x/object.rb +75 -0
  66. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/pathname.rb +0 -0
  67. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/process.rb +0 -0
  68. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/random.rb +0 -0
  69. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/range.rb +0 -0
  70. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/rational.rb +0 -0
  71. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/regexp.rb +0 -0
  72. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/set.rb +0 -0
  73. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/string.rb +0 -0
  74. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/strscan.rb +0 -0
  75. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/symbol.rb +0 -0
  76. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/time.rb +0 -0
  77. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/uri.rb +0 -0
  78. data/{types/ruby-2.x → lib/types/core-ruby-2.x}/yaml.rb +0 -0
  79. data/lib/types/core.rb +4 -0
  80. data/rdl.gemspec +2 -2
  81. data/test/test_le.rb +77 -35
  82. data/test/test_parser.rb +75 -59
  83. data/test/test_rdl.rb +18 -0
  84. data/test/test_typecheck.rb +73 -4
  85. metadata +54 -57
  86. data/lib/rails_types.rb +0 -1
  87. data/types/rails-4.2.1/fixnum.rb +0 -3
  88. data/types/rails-4.2.1/string.rb +0 -3
  89. data/types/rails-tmp/action_dispatch.rb +0 -406
  90. data/types/rails-tmp/active_record.rb +0 -406
  91. data/types/rails-tmp/devise_contracts.rb +0 -216
  92. data/types/ruby-2.x/object.rb +0 -73
@@ -1,406 +0,0 @@
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
@@ -1,216 +0,0 @@
1
- require'rdl'
2
-
3
- module MapperHelper
4
- class << self
5
- attr_accessor :namespace_stack
6
- end
7
-
8
- def self.devise_for_info_valid?(model, type, action, routes, path_prefix)
9
- ctrl_cls = model.to_s.pluralize.camelize + "Controller"
10
- ctrl_cls = eval(ctrl_cls)
11
-
12
- info = get_devise_for_info(model, type, action, path_prefix)
13
- path_helper_method = info[:path_helper][0]
14
- url_helper_method = info[:url_helper][0]
15
- path_helper_method_type = info[:path_helper][0]
16
- url_helper_method_type = info[:url_helper][0]
17
- path = info[:path]
18
- verb = info[:verb]
19
- ctrl = info[:controller]
20
-
21
- # TODO: this part should be in post_task, but need a better way to
22
- # take care of shared code?
23
-
24
- # typesig(ctrl_cls, path_helper_method, path_helper_method_type)
25
- # typesig(ctrl_cls, url_helper_method, url_helper_method_type)
26
-
27
- route_added = routes.any? {|r|
28
- defaults = r.defaults
29
- route_path = r.path.spec.to_s.split('(')[0]
30
-
31
- route_path == path and verb.include?(r.verb) and
32
- defaults[:action] == action.to_s and defaults[:controller] == ctrl
33
- }
34
-
35
- ctrl_cls.instance_methods.include?(path_helper_method) and
36
- ctrl_cls.instance_methods.include?(url_helper_method) and
37
- route_added
38
- end
39
-
40
- def self.get_devise_for_info(model, type, action, path_prefix="")
41
- # TODO: the arg types may be (*Hash), where each Hash is a user_session?
42
- # where is this defined?
43
-
44
- model_s = model.to_s.singularize
45
- model_s_c = model_s.camelize
46
-
47
- ns = MapperHelper.namespace_stack
48
- namespace_str = ns.empty? ? "" : ns.join("_") + "_"
49
- namespace_path_str = ns.empty? ? "" : ns.join("/") + "/"
50
- ctrl_prefix = namespace_path_str == "" ? "devise/" : namespace_path_str
51
-
52
- case type
53
- when :session
54
- case action
55
- when :new
56
- h = :"new_#{namespace_str}#{model_s}_session"
57
- v = [/^GET$/]
58
- p = "#{path_prefix}/#{model}/sign_in"
59
- pht = "(?Hash) -> String"
60
- when :create
61
- h = :"#{namespace_str}#{model_s}_session"
62
- v = [/^POST$/]
63
- p = "#{path_prefix}/#{model}/sign_in"
64
- pht = "(?Hash) -> String"
65
- when :destroy
66
- h = :"destroy_#{namespace_str}#{model_s}_session"
67
- v = [/^DELETE$/]
68
- p = "#{path_prefix}/#{model}/sign_out"
69
- # TODO: Is there a better way to specify arg is a user session?
70
- pht = "(?Hash) -> String"
71
- else
72
- raise Exception, "invalid action for #{type.inspect}"
73
- end
74
-
75
- controller = "#{ctrl_prefix}sessions"
76
- when :password
77
- case action
78
- when :new
79
- h = :"new_#{namespace_str}#{model_s}_password"
80
- v = [/^GET$/]
81
- p = "#{path_prefix}/#{model}/password/new"
82
- pht = "(?Hash) -> String"
83
- when :edit
84
- h = :"edit_#{namespace_str}#{model_s}_password"
85
- v = [/^GET$/]
86
- p = "#{path_prefix}/#{model}/password/edit"
87
- pht = "(?Hash) -> String"
88
- when :update
89
- h = :"#{namespace_str}#{model_s}_password"
90
- v = [/^PUT$/]
91
- p = "#{path_prefix}/#{model}/password"
92
- pht = "(?Hash) -> String"
93
- when :create
94
- h = :"#{namespace_str}#{model_s}_password"
95
- v = [/^POST$/]
96
- p = "#{path_prefix}/#{model}/password"
97
- pht = "(?Hash) -> String"
98
- else
99
- raise Exception, "invalid action for #{type.inspect}"
100
- end
101
-
102
- controller = "#{ctrl_prefix}passwords"
103
- when :confirmation
104
- case action
105
- when :new
106
- h = :"new_#{namespace_str}#{model_s}_confirmation"
107
- v = [/^GET$/]
108
- p = "#{path_prefix}/#{model}/confirmation/new"
109
- pht = "(?Hash) -> String"
110
- when :show
111
- h = :"#{namespace_str}#{model_s}_confirmation"
112
- v = [/^GET$/]
113
- p = "#{path_prefix}/#{model}/confirmation"
114
- pht = "(?Hash) -> String"
115
- when :create
116
- h = :"#{namespace_str}#{model_s}_confirmation"
117
- v = [/^POST$/]
118
- p = "#{path_prefix}/#{model}/confirmation"
119
- pht = "(?Hash) -> String"
120
- else
121
- raise Exception, "invalid action for #{type.inspect}"
122
- end
123
-
124
- controller = "#{ctrl_prefix}confirmations"
125
- else
126
- raise Exception, "invalid action"
127
- end
128
-
129
- ph = :"#{h}_path"
130
- uh = :"#{h}_url"
131
- uht = pht
132
-
133
- {:verb => v, :path => p, :path_helper => [ph, pht], :url_helper => [uh, uht], :controller => controller}
134
- end
135
- end
136
-
137
- module ActionDispatch::Routing
138
- class Mapper
139
- extend RDL
140
-
141
- spec :namespace do
142
- pre_task do |arg|
143
- MapperHelper.namespace_stack = [] if not MapperHelper.namespace_stack
144
- MapperHelper.namespace_stack.push(arg)
145
- end
146
-
147
- post_task do |ret, *arg|
148
- MapperHelper.namespace_stack.pop
149
- end
150
- end
151
-
152
- # TODO: other valid options for devise_for
153
- spec :devise_for do
154
- post_cond do |ret, *args|
155
- model = args[0].to_s
156
- model_s = model.singularize
157
- model_cls = eval(model_s.camelize)
158
-
159
- if args[-1].class == Hash and args[-1].keys.include?(:path_prefix)
160
- path_prefix = "/#{args[-1][:path_prefix]}"
161
- else
162
- path_prefix = ""
163
- end
164
-
165
- routes = Rails.application.routes.routes.to_a
166
-
167
- # default is session
168
- actions = [:new, :create, :destroy]
169
-
170
- session_info_valid = actions.all? {|action|
171
- MapperHelper.devise_for_info_valid?(model, :session, action, routes, path_prefix)
172
- }
173
-
174
- if model_cls.devise_modules.include?(:recoverable)
175
- actions = [:new, :edit, :update, :create]
176
-
177
- password_info_valid = actions.all? {|action|
178
- MapperHelper.devise_for_info_valid?(model, :password, action, routes, path_prefix)
179
- }
180
- else
181
- password_info_valid = true
182
- end
183
-
184
- if model_cls.devise_modules.include?(:confirmable)
185
- actions = [:new, :show, :create]
186
-
187
- confirmation_info_valid = actions.all? {|action|
188
- MapperHelper.devise_for_info_valid?(model, :confirmation, action, routes, path_prefix)
189
- }
190
- else
191
- confirmation_info_valid = true
192
- end
193
-
194
- ns = MapperHelper.namespace_stack
195
- namespace_str = ns.empty? ? "" : ns.join("_") + "_"
196
-
197
- helper_methods = {}
198
- helper_methods[:"current_#{namespace_str}#{model_s}"] = "() -> #{model_cls}"
199
- helper_methods[:"#{namespace_str}#{model_s}_signed_in?"] = "() -> %bool"
200
- helper_methods[:"authenticate_#{namespace_str}#{model_s}!"] = "() -> #{model_cls}"
201
-
202
- helper_info_valid = helper_methods.keys.all? {|m|
203
- ApplicationController.instance_methods.include?(m)
204
- }
205
-
206
- # this should be in post_task? but how to take care of shared code
207
- helper_methods.each {|method, type|
208
- #add_typesig(ApplicationController, method, type)
209
- }
210
-
211
- session_info_valid and password_info_valid and confirmation_info_valid and helper_info_valid
212
- end
213
- end
214
- end
215
- end
216
-