flex_scaffold 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/CHANGELOG +4 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README +169 -0
  4. data/Rakefile +116 -0
  5. data/TODO +23 -0
  6. data/generators/flex_scaffold/USAGE +16 -0
  7. data/generators/flex_scaffold/flex_scaffold_generator.rb +434 -0
  8. data/generators/flex_scaffold/templates/_form.rhtml +1 -0
  9. data/generators/flex_scaffold/templates/_index.rmxml +210 -0
  10. data/generators/flex_scaffold/templates/_list.rhtml +0 -0
  11. data/generators/flex_scaffold/templates/_list.rmxml +17 -0
  12. data/generators/flex_scaffold_resource/USAGE +36 -0
  13. data/generators/flex_scaffold_resource/flex_scaffold_resource_generator.rb +81 -0
  14. data/generators/flex_scaffold_resource/templates/controller.rb +101 -0
  15. data/generators/flex_scaffold_resource/templates/index.rhtml +3 -0
  16. data/generators/flex_scaffold_resource/templates/layout.rhtml +19 -0
  17. data/init.rb +29 -0
  18. data/install.rb +1 -0
  19. data/lib/action_view_helper.rb +49 -0
  20. data/lib/actionscript_helper.rb +81 -0
  21. data/lib/config.rb +49 -0
  22. data/lib/flex_scaffold_plugin.rb +25 -0
  23. data/lib/flexobject_view_helper.rb +132 -0
  24. data/lib/mtag_helper.rb +98 -0
  25. data/lib/mxml_helper.rb +107 -0
  26. data/lib/rest_scaffolding.rb +137 -0
  27. data/lib/validations.rb +180 -0
  28. data/public/crossdomain.xml +6 -0
  29. data/public/history.htm +21 -0
  30. data/public/history.swf +0 -0
  31. data/public/images/add.gif +0 -0
  32. data/public/images/arrow_down.gif +0 -0
  33. data/public/images/arrow_up.gif +0 -0
  34. data/public/images/create.gif +0 -0
  35. data/public/images/delete.gif +0 -0
  36. data/public/images/indicator-small.gif +0 -0
  37. data/public/images/indicator.gif +0 -0
  38. data/public/images/read.gif +0 -0
  39. data/public/images/search.gif +0 -0
  40. data/public/images/update.gif +0 -0
  41. data/public/javascripts/flashobject.js +168 -0
  42. data/public/javascripts/history.js +48 -0
  43. data/public/playerProductInstall.swf +0 -0
  44. data/public/stylesheets/default.css +28 -0
  45. data/tasks/compile_swf.rake +100 -0
  46. data/tasks/flex_scaffold.rake +38 -0
  47. data/uninstall.rb +1 -0
  48. metadata +125 -0
@@ -0,0 +1,434 @@
1
+ require 'rails_generator/generators/components/scaffold/scaffold_generator'
2
+
3
+ class FlexScaffoldingSandbox < ScaffoldingSandbox
4
+
5
+ class << self
6
+ def mxml_tags(record, record_name, options={})
7
+ input_block = options[:input_block] || ""
8
+ filtered_columns = !options[:exclude].blank? ? record.class.content_columns.reject { |column| options[:exclude].include?(column.name) } : record.class.content_columns
9
+ filtered_columns.collect{ |column| input_block.call(record_name, column) }
10
+ end
11
+
12
+ def mxml_form(options)
13
+ Proc.new do |record, column|
14
+ item = "<mx:FormItem label='#{column.human_name}'>"
15
+ case column.type
16
+ when :string, :integer, :decimal, :float
17
+ item << "<mx:TextInput id='field#{prefix(options)}_#{column.name}' text='#{column.default}'/>"
18
+ when :date, :datetime, :time, :timestamp
19
+ item << "<mx:DateField id='field#{prefix(options)}_#{column.name}' yearNavigationEnabled='true'/>"
20
+ when :text, :textarea
21
+ item << "<mx:TextArea id='field#{prefix(options)}_#{column.name}'><mx:text/></mx:TextArea>"
22
+ when :boolean
23
+ item << "<mx:CheckBox id='field#{prefix(options)}_#{column.name}' selected='#{column.default}'/>"
24
+ end
25
+ item << "</mx:FormItem>"
26
+ end
27
+ end
28
+
29
+ def mxml_as_xml_resource(options)
30
+ Proc.new { |record, column| "<#{column.name}>{field#{prefix(options)}_#{column.name}.#{text(column.type)}}</#{column.name}>" }
31
+ end
32
+
33
+ def mxml_grid_column
34
+ Proc.new { |record, column| "<mx:DataGridColumn headerText='#{column.human_name}' dataField='#{column.name}'/>" }
35
+ end
36
+
37
+ def mxml_as_actionscript_form_action(options)
38
+ if options[:prefix] == 'create'
39
+ Proc.new { |record, column| "field#{prefix(options)}_#{column.name}.#{text(column.type)} = #{cast(column)};" }
40
+ else
41
+ Proc.new { |record, column| "field#{prefix(options)}_#{column.name}.#{text(column.type)} = #{record}_grid.selectedItem.#{column.name};" }
42
+ end
43
+ end
44
+
45
+ def mxml_as_actionscript_resource_params(options)
46
+ Proc.new { |record, column| "params['#{record}[#{column.name}]'] = field#{prefix(options)}_#{column.name}.#{text(column.type)};" }
47
+ end
48
+
49
+ def mxml_model_tags(record, record_name, options={})
50
+ input_block = options[:input_block] || ""
51
+ filtered_columns = !options[:exclude].blank? ? record.class.content_columns.reject { |column| options[:exclude].include?(column.name) } : record.class.content_columns
52
+ filtered_columns.collect{ |column| input_block.call(record, column) }
53
+ end
54
+
55
+ # Options:
56
+ # :message text
57
+ # :on (:save, :create, or :update)
58
+
59
+ def mxml_model_validators(options)
60
+ Proc.new do |record, column|
61
+ validations = record.class.new_validations.instance_variable_get(:@validations) rescue nil
62
+ validators = ""
63
+
64
+ field_name, trigger_btn = form_field(options, column), form_submit(options)
65
+
66
+ # validates_format_of :length, :with => /^\d+(in|cm)/
67
+ if has_model_validation?(validations, column, :format)
68
+ validators << <<-MX
69
+ <mx:RegExpValidator
70
+ source="{#{field_name}}" property="text"
71
+ required="#{required?(column.null)}"
72
+ flags="g" expression="#{validation(validations, column, :format, :with).source}"
73
+ noMatchError="#{validation(validations, column, :format, :message)}"
74
+ trigger="{#{field_name}}" triggerEvent="change" />
75
+ MX
76
+ end
77
+ # validates_numericality_of :height_in_meters
78
+ # validates_numericality_of :age, :only_integer => true
79
+ if has_model_validation?(validations, column, :numericality)
80
+ validators << <<-MX
81
+ <mx:NumberValidator
82
+ source="{#{field_name}}" property="text"
83
+ integerError="Enter Integer value"
84
+ required="#{required?(column.null)}"
85
+ minValue="" maxValue="#{column.limit}" domain="int"
86
+ trigger="{#{field_name}}" triggerEvent="change" />
87
+ MX
88
+ end
89
+ # TODO: uniqueness needs to check all the other values in the datagrid
90
+ if has_model_validation?(validations, column, :uniqueness)
91
+ validators << <<-MX
92
+ <!-- Uniqueness not implemented as yet -->
93
+ MX
94
+ end
95
+ # TODO: implement the actionscript to make this work
96
+ # Checks that one fields equals another
97
+ if has_model_validation?(validations, column, :confirmation)
98
+ validators << <<-MX
99
+ <!-- Confirmation not implemented as yet -->
100
+ MX
101
+ end
102
+
103
+ # validates_inclusion_of :gender,
104
+ # :in => %w{ male female },
105
+ # :message => "should be 'male' or 'female'"
106
+ # validates_inclusion_of :age,
107
+ # :in => 0..130,
108
+ # :message => "should be between 0 and 130"
109
+ # TODO: implement inclusion
110
+ if has_model_validation?(validations, column, :inclusion)
111
+ # use :in as range
112
+ if validation(validations, column, :inclusion, :in).is_a?(Range)
113
+ validators << <<-MX
114
+ <mx:NumberValidator
115
+ source="{#{field_name}}" property="text"
116
+ integerError="#{validation(validations, column, :inclusion, :message)}"
117
+ required="#{required?(column.null)}"
118
+ minValue="#{min(validations, column, :inclusion)}"
119
+ maxValue="#{max(validations, column, :inclusion)}"
120
+ domain="int"
121
+ trigger="{#{field_name}}" triggerEvent="change" />
122
+ MX
123
+ end
124
+ # use :in as part of a list or regexp
125
+ if validation(validations, column, :inclusion, :in).is_a?(Array)
126
+ validators << <<-MX
127
+ <mx:RegExpValidator
128
+ source="{#{field_name}}" property="text"
129
+ required="#{required?(column.null)}"
130
+ flags="g" expression="#{in_list(validations, column, :inclusion)}"
131
+ noMatchError="#{validation(validations, column, :inclusion, :message)}"
132
+ trigger="{#{field_name}}" triggerEvent="change" />
133
+ MX
134
+ end
135
+ end
136
+ # validates_exclusion_of :genre,
137
+ # :in => %w{ polka twostep foxtrot },
138
+ # :message => "no wild music allowed"
139
+ # validates_exclusion_of :age,
140
+ # :in => 13..19,
141
+ # :message => "cannot be a teenager"
142
+ # TODO: implement exclusion
143
+ if has_model_validation?(validations, column, :exclusion)
144
+ # use :in as range
145
+ if validation(validations, column, :exclusion, :in).is_a?(Range)
146
+ validators << <<-MX
147
+ <!-- Exclusion (range) not implemented as yet -->
148
+ MX
149
+ end
150
+ # use :in as part of a list or regexp
151
+ if validation(validations, column, :exclusion, :in).is_a?(Array)
152
+ validators << <<-MX
153
+ <!-- Exclusion (list) not implemented as yet -->
154
+ MX
155
+ end
156
+ end
157
+
158
+ # validates_length_of :name, :maximum => 50
159
+ # validates_length_of :password, :in => 6..20
160
+ # validates_length_of :address, :minimum => 10,
161
+ # :message => "seems too short"
162
+ #
163
+ # Options:
164
+ # :in range The length of value must be in range.
165
+ # :minimum integer Value may not be less than the integer characters long.
166
+ # :maximum integer Value may not be greater than integer characters long.
167
+ # :message text The default message depends on the test being performed. The message
168
+ # may contain a single %d sequence, which will be replaced by the
169
+ # maximum, minimum, or exact length required.
170
+ # :on :save, :create, or :update.
171
+ # :too_long text A synonym for :message when :maximum is being used.
172
+ # :too_short text A synonym for :message when :minimum is being used.
173
+ #
174
+ # <mx:StringValidator
175
+ # maxLength="NaN"
176
+ # minLength="NaN"
177
+ # tooLongError="This string is longer than the maximum allowed length."
178
+ # tooShortError="This string is shorter than the minimum allowed length."
179
+ # />
180
+ if has_model_validation?(validations, column, :length)
181
+ validators << <<-MX
182
+ <mx:StringValidator
183
+ source="{#{field_name}}" property="text"
184
+ required="#{required?(column.null)}"
185
+ trigger="{#{field_name}}" triggerEvent="change"
186
+ tooLongError="#{validation(validations, column, :length, :too_long)}"
187
+ tooShortError="#{validation(validations, column, :length, :too_short)}"
188
+ maxLength="#{max(validations, column)}"
189
+ minLength="#{min(validations, column)}" />
190
+ MX
191
+ end
192
+
193
+ # validates_acceptance_of :terms,
194
+ # :message => "Please accept the terms to proceed"
195
+ #
196
+ # Note: this assumes acceptance to be boolean such as a check box
197
+ if has_model_validation?(validations, column, :acceptance)
198
+ validators << <<-MX
199
+ <mx:Validator
200
+ source="{#{field_name}}" property="selected"
201
+ enabled="#{column.null}"
202
+ required="#{required?(column.null)}"
203
+ requiredFieldError="This field is required."
204
+ trigger="{#{trigger_btn}}" triggerEvent="click" />
205
+ MX
206
+ end
207
+ if has_model_validation?(validations, column, :presence)
208
+ validators << <<-MX
209
+ <mx:Validator
210
+ source="{#{field_name}}" property="text"
211
+ enabled="#{column.null}"
212
+ required="#{required?(column.null)}"
213
+ requiredFieldError="#{validation(validations, column, :presence, :message)}"
214
+ trigger="{#{trigger_btn}}" triggerEvent="click" />
215
+ MX
216
+ end
217
+
218
+ validators
219
+
220
+ end
221
+ end
222
+
223
+ private
224
+
225
+ # Returns the regular expression that looks for an item in a string
226
+ # Order of value:
227
+ # * :in => %w{john fred mary} => john|fred|mary
228
+ #
229
+ def in_list(validations, column, type, condition=:in)
230
+ regex = "("
231
+ regex << validation(validations, column, type, condition).join("|") unless validation(validations, column, type, condition).nil?
232
+ regex << ")"
233
+ end
234
+
235
+ # Returns the minimum length
236
+ # Order of value:
237
+ # * :min => 5 => 5
238
+ # * :in => 1..3 => 1
239
+ # * :within => 1..3 => 1
240
+ # * => NaN (default)
241
+ #
242
+ # Note: <tt>:in</tt> and <tt>:within</tt> are not available options
243
+ def min(validations, column, type=:length)
244
+ validation(validations, column, type, :minimum) || (validation(validations, column, type, :in).first unless validation(validations, column, type, :in).nil?) || (validation(validations, column, type, :within).first unless validation(validations, column, type, :within).nil?) || "NaN"
245
+ end
246
+
247
+ # Returns the maximum length correctly depending on whether <tt>:in</tt> is used
248
+ # Order of value:
249
+ # * :maximum => 10 => 10
250
+ # * :in => 1..3 => 3
251
+ # * :within => 1..3 => 3
252
+ # * => NaN (default)
253
+ #
254
+ # Note: <tt>:in</tt> and <tt>:within</tt> are not available options
255
+ def max(validations, column, type=:length)
256
+ validation(validations, column, type, :maximum) || (validation(validations, column, type, :in).last unless validation(validations, column, type, :in).nil?) || (validation(validations, column, type, :within).first unless validation(validations, column, type, :within).nil?) || "NaN"
257
+ end
258
+
259
+ # Returns the schema validations for a column name
260
+ #
261
+ # Example: From the migration
262
+ #
263
+ # t.column :title, :string, :limit=>20
264
+ # t.column :name, :string, :limit=>255, :null=>false
265
+ # t.column :dob, :date
266
+ # t.column :email, :string
267
+ # t.column :description, :text
268
+ # t.column :available, :boolean, :default=>false
269
+ #
270
+ # >> column_validations(validations, :name)
271
+ # => type=>string, limit=>255, deafult=>
272
+
273
+ def column_validations(validations, column)
274
+ result = []
275
+ FlexScaffold::Validations::SCHEMA_INFO.each do |aRule|
276
+ validations.fetch(column.name, nil)
277
+ end
278
+ end
279
+
280
+ # Returns the model validations for a column name
281
+ #
282
+ # Example: From the model
283
+ #
284
+ # validates_format_of :name,
285
+ # :with => /^\w+$/,
286
+ # :message => "is missing or invalid"
287
+ #
288
+ # >> model_validations(validations, :name, :format)
289
+ # => with => /^\w+$/, message => "is missing or invalid", :on=>
290
+
291
+ def model_validations(validations, column, type)
292
+ validations.fetch(column.name, nil).fetch(type.to_s, nil)
293
+ end
294
+
295
+ # Returns the actual validation condition for a column name
296
+ #
297
+ # Example: From the model
298
+ #
299
+ # validates_format_of :name,
300
+ # :with => /^\w+$/,
301
+ # :message => "is missing or invalid"
302
+ #
303
+ # >> validation(validations, :name, :format, :with)
304
+ # => /^\w+$/
305
+
306
+ def validation(validations, column, type, name)
307
+ model_validations(validations, column, type).fetch(name.to_s, nil)
308
+ end
309
+
310
+ # Returns the whether the validation has particular condition for a column name
311
+ #
312
+ # Example: From the model
313
+ #
314
+ # validates_format_of :name,
315
+ # :with => /^\w+$/,
316
+ # :message => "is missing or invalid"
317
+ #
318
+ # >> has_vvalidation_condition?(validations, :name, :format)
319
+ # => true
320
+ #
321
+ # >> has_validation_condition?(validations, :name, :inclusion)
322
+ # => false
323
+
324
+ def has_validation_condition?(validations, column, type)
325
+ validation_condition.fetch(column.name).has_key?(type.to_s) rescue false
326
+ end
327
+ # Returns the whether model has the validation for a column name
328
+ #
329
+ # Example: From the model
330
+ #
331
+ # validates_format_of :name,
332
+ # :with => /^\w+$/,
333
+ # :message => "is missing or invalid"
334
+ #
335
+ # >> has_model_validation?(validations, :name, :format)
336
+ # => true
337
+ #
338
+ # >> has_model_validation?(validations, :name, :inclusion)
339
+ # => false
340
+
341
+ def has_model_validation?(validations, column, type)
342
+ validations.fetch(column.name).has_key?(type.to_s) rescue false
343
+ end
344
+
345
+ def prefix(options)
346
+ !options[:prefix].empty? ? "_#{options[:prefix]}" : ""
347
+ end
348
+
349
+ def text(val=nil)
350
+ (val.to_sym != :boolean) ? "text" : "selected"
351
+ end
352
+
353
+ def required?(value)
354
+ !value
355
+ end
356
+
357
+ def cast(column)
358
+ (column.type.to_sym != :boolean) ? "'#{column.default}'" : "#{column.default}"
359
+ end
360
+
361
+ def form_field(options, column)
362
+ (options[:prefix] == 'create') ? "field_create_#{column.name}" : "field_edit_#{column.name}"
363
+ end
364
+
365
+ def form_submit(options)
366
+ (options[:prefix] == 'create') ? "btn_add_create" : "btn_update_edit"
367
+ end
368
+
369
+ end
370
+
371
+ end
372
+
373
+ class FlexScaffoldGenerator < ScaffoldGenerator
374
+
375
+ alias_method :base_controller_file_path, :controller_file_path
376
+
377
+ def manifest
378
+ record do |m|
379
+
380
+ m.class_collisions controller_class_path, "#{controller_class_name}Controller", "#{controller_class_name}ControllerTest", "#{controller_class_name}Helper"
381
+ m.class_collisions class_path, class_name, "#{singular_name}Test"
382
+
383
+ m.directory File.join('app/flex', class_path)
384
+ m.directory File.join('app/flex' ,"#{plural_name}")
385
+
386
+ m.complex_template '_index.rmxml', File.join('app/flex', "#{plural_name}", "_#{plural_name}.mxml"),
387
+ :insert => '_form.rhtml',
388
+ :sandbox => lambda { create_sandbox },
389
+ :mark_id => singular_name,
390
+ :assigns => {:fields_as_xml => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_as_xml_resource(:prefix=>'create'))},
391
+ :fields_as_update_params => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_as_actionscript_resource_params(:prefix=>'edit'))},
392
+ :fields_as_create_text => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_as_actionscript_form_action(:prefix=>'create'))},
393
+ :fields_as_edit_text => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_as_actionscript_form_action(:prefix=>'edit'))},
394
+ :fields_as_input_edit => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_form(:prefix=>'edit'))},
395
+ :fields_as_input_create => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_form(:prefix=>'create'))},
396
+ :model_validators_create => lambda {FlexScaffoldingSandbox.mxml_model_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_model_validators(:prefix=>'create'))},
397
+ :model_validators_edit => lambda {FlexScaffoldingSandbox.mxml_model_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_model_validators(:prefix=>'edit'))}
398
+ }
399
+
400
+ m.complex_template '_list.rmxml', File.join('app/flex', "#{plural_name}", "_list.mxml"),
401
+ :insert => '_list.rhtml',
402
+ :sandbox => lambda { create_sandbox },
403
+ :mark_id => singular_name,
404
+ :assigns => {:fields_as_grid => lambda {FlexScaffoldingSandbox.mxml_tags(model_instance, singular_name, :input_block => FlexScaffoldingSandbox.mxml_grid_column)}}
405
+
406
+
407
+ end
408
+
409
+ end
410
+
411
+ def scaffold_name
412
+ FlexScaffold::Config.plugin_name
413
+ end
414
+
415
+ def controller_file_path
416
+ "/" + base_controller_file_path
417
+ end
418
+
419
+ def create_sandbox
420
+ sandbox = FlexScaffoldingSandbox.new
421
+ sandbox.singular_name = singular_name
422
+ begin
423
+ sandbox.instance_variable_set(:@validations, class_name.constantize.new_validations)
424
+ sandbox.model_instance = model_instance
425
+ sandbox.instance_variable_set("@#{singular_name}", sandbox.model_instance)
426
+ rescue ActiveRecord::StatementInvalid => e
427
+ logger.error "Before updating scaffolding from new DB schema, try creating a table from your model (#{class_name} - try rake db:migrate)"
428
+ raise SystemExit
429
+ end
430
+ sandbox.suffix = suffix
431
+ sandbox
432
+ end
433
+
434
+ end
@@ -0,0 +1,210 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
4
+ creationComplete="{resourceGet.send();}"
5
+ xmlns:fxrails="*"
6
+ backgroundGradientColors="[#808080, #ffffff]">
7
+
8
+ <mx:Style source="stylesheets/flex_scaffold/default.css"/>
9
+
10
+ <mx:HTTPService id="resourceGet" url="/<%= plural_name %>.xml" useProxy="false" method="GET"/>
11
+ <mx:HTTPService id="resourcePut" useProxy="false" method="POST" result="resourceGet.send();handlePutResultHttpService(event)" resultFormat="e4x"/>
12
+ <mx:HTTPService id="resourceDelete" useProxy="false" method="POST" result="resourceGet.send();handleDeleteResultHttpService(event)" resultFormat="e4x"/>
13
+ <mx:HTTPService id="resourcePost" url="/<%= plural_name %>.xml" useProxy="false" method="POST" result="resourceGet.send();handlePostResultHttpService(event)" resultFormat="e4x"
14
+ contentType="application/xml">
15
+ <mx:request xmlns="">
16
+ <<%= singular_name %>>
17
+ <%= fields_as_xml.call -%>
18
+ </<%= singular_name %>>
19
+ </mx:request>
20
+ </mx:HTTPService>
21
+
22
+ <mx:Script>
23
+ <![CDATA[
24
+ import mx.rpc.events.ResultEvent
25
+ import mx.controls.Alert;
26
+
27
+ [Bindable]
28
+ private var _error:String;
29
+
30
+ private function clearErrorMessage():void {_error = ""}
31
+
32
+ private function handleDeleteResultHttpService(event:ResultEvent):void {
33
+ var result:XML = XML(event.result)
34
+ if (!(result == null || result == "")) {
35
+ _error = result;
36
+ } else {
37
+ _error = "Item Deleted";
38
+ }
39
+ }
40
+
41
+ private function handlePutResultHttpService(event:ResultEvent):void {
42
+ var result:XML = XML(event.result)
43
+ if (!(result == null || result == "")) {
44
+ _error = result;
45
+ } else {
46
+ _error = "Item Updated";
47
+ currentState = '';
48
+ }
49
+ }
50
+
51
+ private function handlePostResultHttpService(event:ResultEvent):void {
52
+ var result:XML = XML(event.result)
53
+ if (!(result == null || result == "")) {
54
+ _error = result;
55
+ } else {
56
+ _error = "Item Created";
57
+ currentState = '';
58
+ }
59
+ }
60
+
61
+ private function createHandler(event:Event):void {
62
+ currentState = 'Create'
63
+ clearErrorMessage()
64
+ <%= fields_as_create_text.call -%>
65
+ btn_add_create.addEventListener('click', createResource);
66
+ btn_cancel_create.addEventListener('click', cancelCreate);
67
+ }
68
+
69
+ public function createResource(event:Event) : void
70
+ {
71
+ resourcePost.send();
72
+ }
73
+
74
+ public function cancelCreate(event:Event) : void
75
+ {
76
+ clearErrorMessage()
77
+ currentState = '';
78
+ }
79
+
80
+ public function deleteResource(id:String):void {
81
+ resourceDelete.url = "/<%= plural_name %>/" + id + ".xml";
82
+ resourceDelete.send({_method: "DELETE"});
83
+ }
84
+
85
+ ]]>
86
+ </mx:Script>
87
+
88
+ <mx:Script>
89
+ <![CDATA[
90
+ import mx.controls.Alert;
91
+ import mx.events.CloseEvent;
92
+
93
+ public function deleteHandler(event:Event) : void
94
+ {
95
+ Alert.show("Are you sure you want to delete this item?", "Delete Item", 3, this,
96
+ function(event:CloseEvent):void
97
+ {
98
+ if (event.detail==Alert.YES)
99
+ clearErrorMessage()
100
+ mx.core.Application.application.deleteResource(<%= singular_name %>_grid.selectedItem.id);
101
+ });
102
+ }
103
+ ]]>
104
+ </mx:Script>
105
+
106
+
107
+ <mx:Script>
108
+ <![CDATA[
109
+
110
+ public function updateHandler(event:Event) : void
111
+ {
112
+ clearErrorMessage()
113
+ currentState = 'Edit';
114
+ <%= fields_as_edit_text.call -%>
115
+ btn_update_edit.addEventListener('click', updateResource);
116
+ btn_cancel_edit.addEventListener('click', cancelEdit);
117
+ }
118
+
119
+ public function updateResource(event:Event) : void
120
+ {
121
+ var params:Object = new Object();
122
+ params['_method'] = "PUT";
123
+ <%= fields_as_update_params.call -%>
124
+
125
+ resourcePut.url = "/<%= plural_name %>/" + <%= singular_name %>_grid.selectedItem.id + ".xml";
126
+ resourcePut.send(params);
127
+ }
128
+
129
+ public function cancelEdit(event:Event) : void
130
+ {
131
+ clearErrorMessage()
132
+ currentState = '';
133
+ }
134
+ ]]>
135
+ </mx:Script>
136
+
137
+ <mx:states>
138
+ <mx:State name="Create">
139
+ <mx:RemoveChild target="{hbox_create}"/>
140
+ <mx:AddChild relativeTo="{<%= singular_name %>_grid}" position="before">
141
+ <mx:target>
142
+ <mx:Form id="create_form">
143
+ <%= fields_as_input_create.call -%>
144
+ <mx:ControlBar width="100%">
145
+ <mx:Spacer width="50"/>
146
+ <mx:Button label="Create" id="btn_add_create"/>
147
+ <mx:LinkButton label="Cancel" id="btn_cancel_create"/>
148
+ </mx:ControlBar>
149
+ </mx:Form>
150
+ </mx:target>
151
+ </mx:AddChild>
152
+ </mx:State>
153
+
154
+ <mx:State name="Edit">
155
+ <mx:AddChild relativeTo="{<%= singular_name %>_grid}" position="before">
156
+ <mx:target>
157
+ <mx:Form id="edit_form">
158
+ <%= fields_as_input_edit.call -%>
159
+ <mx:ControlBar width="100%">
160
+ <mx:Spacer width="50"/>
161
+ <mx:Button label="Update" id="btn_update_edit" />
162
+ <mx:LinkButton label="Cancel" id="btn_cancel_edit"/>
163
+ </mx:ControlBar>
164
+ </mx:Form>
165
+ </mx:target>
166
+ </mx:AddChild>
167
+ </mx:State>
168
+
169
+ </mx:states>
170
+
171
+ <mx:transitions>
172
+ <mx:Transition id="createItem" fromState="*" toState="Create">
173
+ <mx:Sequence targets="{[createPanel]}">
174
+ <mx:RemoveChildAction/>
175
+ <mx:Resize target="{createPanel}"/>
176
+ <mx:AddChildAction/>
177
+ </mx:Sequence>
178
+ </mx:Transition>
179
+
180
+ <mx:Transition id="addItem" fromState="Create" toState="*">
181
+ <mx:Sequence targets="{[createPanel]}">
182
+ <mx:RemoveChildAction/>
183
+ <mx:Resize target="{createPanel}"/>
184
+ <mx:AddChildAction/>
185
+ </mx:Sequence>
186
+ </mx:Transition>
187
+
188
+ <mx:Transition id="editItem" fromState="*" toState="Edit">
189
+ <mx:Sequence targets="{[createPanel]}">
190
+ <mx:RemoveChildAction/>
191
+ <mx:Resize target="{createPanel}"/>
192
+ <mx:AddChildAction/>
193
+ </mx:Sequence>
194
+ </mx:Transition>
195
+ </mx:transitions>
196
+
197
+ <%= model_validators_create.call %>
198
+ <%= model_validators_edit.call %>
199
+
200
+ <mx:Panel title="<%= plural_name.capitalize %>" id="createPanel">
201
+
202
+ <mx:HBox id="hbox_create" width="90%" horizontalAlign="right" height="40" horizontalGap="8" verticalAlign="middle" >
203
+ <mx:Button label="Create" id="btn_create" styleName="btn_create" icon="@Embed('images/flex_scaffold/create.gif')" click="mx.core.Application.application.createHandler(event);"/>
204
+ </mx:HBox>
205
+ <mx:Text id="error" styleName="error" htmlText="{_error}" color="#ff0033"/>
206
+ <fxrails:_list id="<%= singular_name %>_grid" dataProvider="{resourceGet.lastResult.<%= plural_name %>.<%= singular_name %>}" />
207
+
208
+ </mx:Panel>
209
+
210
+ </mx:Application>
File without changes
@@ -0,0 +1,17 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+
3
+ <mx:DataGrid xmlns:mx="http://www.adobe.com/2006/mxml">
4
+ <mx:columns>
5
+ <%= fields_as_grid.call %>
6
+ <mx:DataGridColumn editable="false" width="120">
7
+ <mx:itemRenderer>
8
+ <mx:Component>
9
+ <mx:Box direction="horizontal">
10
+ <mx:LinkButton label="Delete" click="mx.core.Application.application.deleteHandler(event);"/>
11
+ <mx:LinkButton label="Edit" click="mx.core.Application.application.updateHandler(event);"/>
12
+ </mx:Box>
13
+ </mx:Component>
14
+ </mx:itemRenderer>
15
+ </mx:DataGridColumn>
16
+ </mx:columns>
17
+ </mx:DataGrid>