restfulx 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/Rakefile +65 -30
  2. data/VERSION.yml +4 -0
  3. data/app_generators/rx_app/rx_app_generator.rb +25 -9
  4. data/app_generators/rx_app/templates/actionscript.properties +3 -3
  5. data/app_generators/rx_app/templates/actionscriptair.properties +3 -3
  6. data/app_generators/rx_app/templates/app.yaml.erb +1 -1
  7. data/app_generators/rx_app/templates/default_tasks.rake +5 -18
  8. data/app_generators/rx_app/templates/generate.rb +1 -1
  9. data/app_generators/rx_app/templates/index.html.erb +1 -1
  10. data/app_generators/rx_app/templates/mainair-app.xml +3 -3
  11. data/app_generators/rx_app/templates/mainapp.mxml +123 -2
  12. data/app_generators/rx_app/templates/project-textmate.erb +4 -4
  13. data/app_generators/rx_app/templates/project.properties +1 -1
  14. data/app_generators/rx_app/templates/projectair.properties +1 -1
  15. data/app_generators/rx_app/templates/restfulx.yml +25 -0
  16. data/bin/rx-gen +1 -1
  17. data/lib/restfulx/active_foo.rb +0 -8
  18. data/lib/restfulx/active_record_tasks.rb +9 -0
  19. data/lib/restfulx/active_record_uuid_helper.rb +17 -0
  20. data/lib/restfulx/configuration.rb +19 -31
  21. data/lib/restfulx/rails/schema_to_yaml/extensions/enumerable.rb +8 -0
  22. data/lib/restfulx/rails/schema_to_yaml/settings/config.rb +17 -0
  23. data/lib/restfulx/rails/schema_to_yaml/settings/core.rb +70 -0
  24. data/lib/restfulx/rails/schema_to_yaml.rb +121 -0
  25. data/lib/restfulx/rails/swf_helper.rb +1 -6
  26. data/lib/restfulx/tasks.rb +68 -42
  27. data/lib/restfulx.rb +4 -35
  28. data/rails_generators/rx_config/USAGE +2 -1
  29. data/rails_generators/rx_config/rx_config_generator.rb +80 -53
  30. data/rails_generators/rx_config/templates/actionscript.properties +3 -3
  31. data/rails_generators/rx_config/templates/actionscriptair.properties +3 -3
  32. data/rails_generators/rx_config/templates/flex_controller.erb +4 -0
  33. data/rails_generators/rx_config/templates/{index.html.erb → index.erb} +2 -4
  34. data/rails_generators/rx_config/templates/mainair-app.xml +3 -3
  35. data/rails_generators/rx_config/templates/mainapp.mxml +100 -2
  36. data/rails_generators/rx_config/templates/project-textmate.erb +4 -4
  37. data/rails_generators/rx_config/templates/project.properties +1 -1
  38. data/rails_generators/rx_config/templates/projectair.properties +1 -1
  39. data/rails_generators/rx_config/templates/restfulx.erb +38 -0
  40. data/rails_generators/rx_config/templates/restfulx.yml +55 -4
  41. data/rails_generators/rx_config/templates/restfulx_tasks.rake +3 -0
  42. data/rails_generators/rx_config/templates/routes.erb +47 -0
  43. data/rails_generators/rx_controller/rx_controller_generator.rb +9 -6
  44. data/rails_generators/rx_controller/templates/controller.as.erb +7 -9
  45. data/rails_generators/rx_main_app/rx_main_app_generator.rb +60 -0
  46. data/rails_generators/rx_main_app/templates/mainapp.mxml +129 -0
  47. data/rails_generators/rx_scaffold/rx_scaffold_generator.rb +88 -34
  48. data/rails_generators/rx_scaffold/templates/{controller.rb.erb → controllers/default.rb.erb} +29 -1
  49. data/rails_generators/rx_scaffold/templates/controllers/resource_controller.rb.erb +23 -0
  50. data/rails_generators/rx_scaffold/templates/fixtures.yml.erb +9 -5
  51. data/{generators/rx_scaffold/templates/component.mxml.erb → rails_generators/rx_scaffold/templates/layouts/default.erb} +75 -59
  52. data/rails_generators/rx_scaffold/templates/migration.rb.erb +29 -2
  53. data/rails_generators/rx_scaffold/templates/model.as.erb +33 -2
  54. data/rails_generators/rx_scaffold/templates/model.rb.erb +36 -1
  55. data/rails_generators/rx_yaml_scaffold/rx_yaml_scaffold_generator.rb +29 -10
  56. data/{generators → rxgen_generators}/rx_controller/rx_controller_generator.rb +7 -5
  57. data/{generators → rxgen_generators}/rx_controller/templates/assist.py +3 -3
  58. data/{generators → rxgen_generators}/rx_controller/templates/controller.as.erb +8 -6
  59. data/rxgen_generators/rx_controller/templates/iso8601.py +92 -0
  60. data/rxgen_generators/rx_main_app/USAGE +8 -0
  61. data/{generators → rxgen_generators}/rx_main_app/rx_main_app_generator.rb +10 -5
  62. data/rxgen_generators/rx_main_app/templates/mainapp.mxml +152 -0
  63. data/{generators → rxgen_generators}/rx_scaffold/rx_scaffold_generator.rb +6 -5
  64. data/{rails_generators → rxgen_generators}/rx_scaffold/templates/component.mxml.erb +24 -52
  65. data/spec/restfulx_spec.rb +1 -4
  66. data/spec/spec_helper.rb +0 -3
  67. data/tasks/restfulx.rake +2 -0
  68. metadata +102 -81
  69. data/History.txt +0 -7
  70. data/Manifest.txt +0 -127
  71. data/generators/rx_main_app/templates/mainapp.mxml +0 -35
  72. data/rdoc/generators/template/html/jamis.rb +0 -588
  73. data/tasks/ann.rake +0 -80
  74. data/tasks/bones.rake +0 -20
  75. data/tasks/gem.rake +0 -201
  76. data/tasks/git.rake +0 -40
  77. data/tasks/manifest.rake +0 -48
  78. data/tasks/notes.rake +0 -27
  79. data/tasks/post_load.rake +0 -39
  80. data/tasks/rdoc.rake +0 -50
  81. data/tasks/rubyforge.rake +0 -55
  82. data/tasks/setup.rb +0 -279
  83. data/tasks/spec.rake +0 -54
  84. data/tasks/svn.rake +0 -47
  85. data/tasks/test.rake +0 -40
  86. data/test/rails/playing_around_in_a_console.txt +0 -71
  87. /data/{generators → rails_generators}/rx_main_app/USAGE +0 -0
  88. /data/{generators → rxgen_generators}/rx_config/USAGE +0 -0
  89. /data/{generators → rxgen_generators}/rx_config/rx_config_generator.rb +0 -0
  90. /data/{generators → rxgen_generators}/rx_controller/USAGE +0 -0
  91. /data/{generators → rxgen_generators}/rx_controller/templates/restful.py +0 -0
  92. /data/{generators → rxgen_generators}/rx_main_app/templates/main.py.erb +0 -0
  93. /data/{generators → rxgen_generators}/rx_scaffold/USAGE +0 -0
  94. /data/{generators → rxgen_generators}/rx_scaffold/templates/controller.py.erb +0 -0
  95. /data/{generators → rxgen_generators}/rx_scaffold/templates/model.as.erb +0 -0
  96. /data/{generators → rxgen_generators}/rx_scaffold/templates/model.py.erb +0 -0
  97. /data/{generators → rxgen_generators}/rx_yaml_scaffold/USAGE +0 -0
  98. /data/{generators → rxgen_generators}/rx_yaml_scaffold/rx_yaml_scaffold_generator.rb +0 -0
@@ -8,25 +8,34 @@
8
8
  <% for model in belongs_tos -%>
9
9
  import <%= base_package %>.models.<%= model.camelcase %>;
10
10
  <% end -%>
11
+ <% if attachment_field.size > 0 -%>
12
+ import org.restfulx.utils.RxFileReference;
13
+ <% end -%>
11
14
 
12
15
  [Bindable]
13
- private var _<%= class_name.dcfirst %>:<%= class_name %> = new <%= class_name %>();
16
+ private var <%= class_name.dcfirst %>:<%= class_name %> = new <%= class_name %>();
17
+ <% if attachment_field.size > 0 -%>
18
+ [Bindable]
19
+ private var fileName:String = "None selected";
20
+
21
+ private var file:RxFileReference;
22
+ <% end -%>
14
23
 
15
24
  private function new<%= class_name %>():void {
16
- _<%= class_name.dcfirst %> = new <%= class_name %>();
25
+ <%= class_name.dcfirst %> = new <%= class_name %>();
17
26
  <%= class_name.dcfirst.pluralize %>List.selectedIndex = -1;
18
27
  }
19
28
 
20
29
  private function save<%= class_name %>():void {
21
- if (_<%= class_name.dcfirst %>.id) {
22
- update<%= class_name %>();
30
+ updateModelProperties();
31
+ if (<%= class_name.dcfirst %>.id) {
32
+ <%= class_name.dcfirst %>.update({onSuccess: on<%= class_name %>Update});
23
33
  } else {
24
- create<%= class_name %>();
34
+ <%= class_name.dcfirst %>.create({onSuccess: on<%= class_name %>Create});
25
35
  }
26
36
  }
27
37
 
28
- private function create<%= class_name %>():void {
29
- var <%= class_name.dcfirst %>:<%= class_name %> = new <%= class_name %>();
38
+ private function updateModelProperties():void {
30
39
  <% for attribute in attributes -%>
31
40
  <% if attribute.type == :boolean -%>
32
41
  <%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_name %>CheckBox.selected;
@@ -41,64 +50,64 @@
41
50
  <% else -%>
42
51
  <%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_type %>(<%= attribute.flex_name %>TextInput.text);
43
52
  <% end -%>
44
- <% end -%>
45
-
53
+ <% end -%>
46
54
  <% for model in belongs_tos -%>
47
55
  <%= class_name.dcfirst %>.<%= model.camelcase(:lower) %> = <%= model.camelcase %>(<%= model.camelcase(:lower) %>ComboBox.selectedItem);
48
56
  <% end -%>
49
- <%= class_name.dcfirst %>.create({onSuccess: on<%= class_name %>Create});
50
- }
51
-
52
- private function update<%= class_name %>():void {
53
- <% for attribute in attributes -%>
54
- <% if attribute.type == :boolean -%>
55
- _<%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_name %>CheckBox.selected;
56
- <% elsif attribute.type == :string -%>
57
- _<%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_name %>TextInput.text;
58
- <% elsif attribute.type == :text -%>
59
- _<%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_name %>TextArea.text;
60
- <% elsif attribute.type == :datetime || attribute.type == :time -%>
61
- _<%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_name %>DateTimeTextInput.date;
62
- <% elsif attribute.type == :date -%>
63
- _<%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_name %>DateField.selectedDate;
64
- <% else -%>
65
- _<%= class_name.dcfirst %>.<%= attribute.flex_name %> = <%= attribute.flex_type %>(<%= attribute.flex_name %>TextInput.text);
66
- <% end -%>
57
+ <% if attachment_field.size > 0 -%>
58
+ <%= class_name.dcfirst %>.attachment = file;
67
59
  <% end -%>
68
-
69
- <% for model in belongs_tos -%>
70
- _<%= class_name.dcfirst %>.<%= model.camelcase(:lower) %> = <%= model.camelcase %>(<%= model.camelcase(:lower) %>ComboBox.selectedItem);
71
- <% end -%>
72
- _<%= class_name.dcfirst %>.update({onSuccess: on<%= class_name %>Update});
73
60
  }
74
-
61
+
75
62
  private function destroy<%= class_name %>():void {
76
- _<%= class_name.dcfirst %>.destroy({onSuccess: on<%= class_name %>Destroy});
63
+ <%= class_name.dcfirst %>.destroy({onSuccess: on<%= class_name %>Destroy});
77
64
  }
78
-
65
+
79
66
  private function on<%= class_name %>Select():void {
80
- _<%= class_name.dcfirst %> = RxUtils.clone(<%= class_name.dcfirst.pluralize %>List.selectedItem) as <%= class_name %>;
67
+ <%= class_name.dcfirst %> = RxUtils.clone(<%= class_name.dcfirst.pluralize %>List.selectedItem) as <%= class_name %>;
81
68
  }
82
-
83
- private function on<%= class_name %>Create(<%= class_name.dcfirst %>:<%= class_name %>):void {
84
- _<%= class_name.dcfirst %> = new <%= class_name %>;
85
- }
86
-
87
- private function on<%= class_name %>Update(<%= class_name.dcfirst %>:<%= class_name %>):void {
88
- <%= class_name.dcfirst.pluralize %>List.selectedItem = <%= class_name.dcfirst %>;
89
- _<%= class_name.dcfirst %> = RxUtils.clone(<%= class_name.dcfirst %>) as <%= class_name %>;
69
+
70
+ private function on<%= class_name %>Create(result:<%= class_name %>):void {
71
+ <%= class_name.dcfirst %> = new <%= class_name %>;
90
72
  }
91
-
92
- private function on<%= class_name %>Destroy(<%= class_name.dcfirst %>:<%= class_name %>):void {
93
- on<%= class_name %>Create(<%= class_name.dcfirst %>);
73
+
74
+ private function on<%= class_name %>Update(result:<%= class_name %>):void {
75
+ <%= class_name.dcfirst.pluralize %>List.selectedItem = result;
76
+ on<%= class_name %>Select();
94
77
  }
78
+
79
+ private function on<%= class_name %>Destroy(result:<%= class_name %>):void {
80
+ on<%= class_name %>Create(result);
81
+ }
82
+ <% if attachment_field.size > 0 -%>
95
83
 
96
- private function canDelete<%= class_name %>(<%= class_name.dcfirst %>:<%= class_name %>):Boolean {
97
- return <%= class_name.dcfirst %> != null && !RxUtils.isEmpty(<%= class_name.dcfirst %>.id);
84
+ private function chooseFile():void {
85
+ file = new RxFileReference("<%= attachment_field[0].camelcase(:lower) %>");
86
+ file.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
87
+ file.addEventListener(Event.SELECT, selectFile, false, 0, true);
88
+ file.addEventListener(Event.CANCEL, cancelBrowse, false, 0, true);
89
+ file.browse();
98
90
  }
91
+
92
+ private function selectFile(event:Event):void {
93
+ fileSelected(event)
94
+ }
95
+
96
+ private function cancelBrowse(event:Event):void {
97
+ file = null;
98
+ }
99
+
100
+ private function fileSelected(event:Event):void {
101
+ fileName = RxFileReference(event.target).name;
102
+ }
103
+
104
+ private function ioErrorHandler(event:Event):void {
105
+ fileChooser.errorString = "Failed to selected a file. Please try again.";
106
+ }
107
+ <% end -%>
99
108
  ]]></mx:Script>
100
109
  <mx:Panel id="<%= class_name.dcfirst.pluralize %>Panel"
101
- title="<%= class_name.pluralize %>" cornerRadius="0" dropShadowEnabled="false" borderStyle="solid"
110
+ title="<%= class_name.pluralize %>" cornerRadius="0" dropShadowEnabled="false" borderStyle="solid"
102
111
  borderThickness="1" backgroundColor="#EEEEEE" width="25%" height="100%">
103
112
  <mx:List id="<%= class_name.dcfirst.pluralize %>List"
104
113
  width="100%" height="100%"
@@ -109,24 +118,31 @@
109
118
  click="new<%= class_name %>()"/>
110
119
  </mx:ControlBar>
111
120
  </mx:Panel>
112
- <mx:Panel title="Edit <%= class_name %>" cornerRadius="0" dropShadowEnabled="false" borderStyle="solid"
121
+ <mx:Panel title="Edit <%= class_name %>" cornerRadius="0" dropShadowEnabled="false" borderStyle="solid"
113
122
  borderThickness="1" backgroundColor="#EEEEEE" width="75%" height="100%">
114
123
  <mx:Form width="100%" height="100%">
115
124
  <% for attribute in attributes -%>
116
125
  <mx:FormItem label="<%= attribute.flex_name.ucfirst %>" width="100%">
117
126
  <% if attribute.type == :boolean -%>
118
- <mx:CheckBox id="<%= attribute.flex_name %>CheckBox" selected="{_<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
127
+ <mx:CheckBox id="<%= attribute.flex_name %>CheckBox" selected="{<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
119
128
  <% elsif attribute.type == :string -%>
120
- <mx:TextInput id="<%= attribute.flex_name %>TextInput" width="100%" text="{_<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
129
+ <mx:TextInput id="<%= attribute.flex_name %>TextInput" width="100%" text="{<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
121
130
  <% elsif attribute.type == :text -%>
122
- <mx:TextArea id="<%= attribute.flex_name %>TextArea" width="100%" height="200" text="{_<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
131
+ <mx:TextArea id="<%= attribute.flex_name %>TextArea" width="100%" height="200" text="{<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
123
132
  <% elsif attribute.type == :datetime || attribute.type == :time -%>
124
- <rx:DateTimeTextInput id="<%= attribute.flex_name %>DateTimeTextInput" width="200" date="{_<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
133
+ <rx:DateTimeTextInput id="<%= attribute.flex_name %>DateTimeTextInput" width="200" date="{<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
125
134
  <% elsif attribute.type == :date -%>
126
- <mx:DateField id="<%= attribute.flex_name %>DateField" selectedDate="{_<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
135
+ <mx:DateField id="<%= attribute.flex_name %>DateField" selectedDate="{<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
127
136
  <% else -%>
128
- <mx:TextInput id="<%= attribute.flex_name %>TextInput" width="100%" text="{_<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
137
+ <mx:TextInput id="<%= attribute.flex_name %>TextInput" width="100%" text="{<%= class_name.dcfirst %>.<%= attribute.flex_name %>}"/>
138
+ <% end -%>
139
+ </mx:FormItem>
129
140
  <% end -%>
141
+ <% if attachment_field.size > 0 -%>
142
+ <mx:FormItem label="<%= attachment_field[0].camelcase %>:" width="100%" id="fileChooser">
143
+ <mx:Button label="Browse…" id="fileBrowseButton" click="chooseFile()"/>
144
+ <mx:Label text="{fileName}" maxWidth="190"/>
145
+ <mx:Image source="{<%= class_name.dcfirst %>.attachmentUrl}"/>
130
146
  </mx:FormItem>
131
147
  <% end -%>
132
148
  <% for model in belongs_tos -%>
@@ -134,7 +150,7 @@
134
150
  <mx:ComboBox id="<%= model.camelcase(:lower) %>ComboBox" width="200"
135
151
  labelField="{<%= model.camelcase %>.LABEL}"
136
152
  dataProvider="{Rx.models.index(<%= model.camelcase %>)}" prompt="<%= model.camelcase %> ..."
137
- selectedItem="{_<%= class_name.dcfirst %>.<%= model.camelcase(:lower) %>}" />
153
+ selectedItem="{<%= class_name.dcfirst %>.<%= model.camelcase(:lower) %>}"/>
138
154
  </mx:FormItem>
139
155
  <% end -%>
140
156
  </mx:Form>
@@ -142,7 +158,7 @@
142
158
  <mx:Button label="Save <%= class_name %>" width="50%" height="30"
143
159
  click="save<%= class_name %>()"/>
144
160
  <mx:Button label="Delete <%= class_name %>" width="50%" height="30"
145
- enabled="{canDelete<%= class_name %>(_<%= class_name.dcfirst %>)}"
161
+ enabled="{RxUtils.canDeleteModel(<%= class_name.dcfirst %>)}"
146
162
  click="destroy<%= class_name %>()"/>
147
163
  </mx:ControlBar>
148
164
  </mx:Panel>
@@ -1,12 +1,39 @@
1
1
  class <%= migration_name %> < ActiveRecord::Migration
2
2
  def self.up
3
+ <% if distributed -%>
4
+ create_table :<%= table_name %>, :id => false do |t|
5
+ t.string :id
6
+ <% else -%>
3
7
  create_table :<%= table_name %> do |t|
4
- <% for attribute in attributes -%>
5
- t.<%= attribute.type %> :<%= attribute.name %>
8
+ <% end -%>
9
+ <% for attribute in args_for_generation -%>
10
+ t.<%= attribute.split(':')[1] %> :<%= attribute.split(':')[0] %>
6
11
  <% end -%>
7
12
  <% for model in belongs_tos -%>
13
+ <% if distributed -%>
14
+ t.string :<%= model %>_id
15
+ <% else -%>
8
16
  t.references :<%= model %>
9
17
  <% end -%>
18
+ <% end -%>
19
+ <% if attachment_field.size > 0 -%>
20
+ <% if RxSettings.attachment_plugin == 'paperclip' -%>
21
+ # For paperclip
22
+ t.column :avatar_file_name, :string
23
+ t.column :avatar_content_type, :string
24
+ t.column :avatar_file_size, :integer
25
+ t.column :avatar_updated_at, :datetime
26
+ <% elsif RxSettings.attachment_plugin == 'attachment_fu' -%>
27
+ # For attachment_fu
28
+ t.column :parent_id, :integer
29
+ t.column :content_type, :string
30
+ t.column :filename, :string
31
+ t.column :thumbnail, :string
32
+ t.column :size, :integer
33
+ t.column :width, :integer
34
+ t.column :height, :integer
35
+ <% end -%>
36
+ <% end -%>
10
37
  <% unless options[:skip_timestamps] %>
11
38
  t.timestamps
12
39
  <% end -%>
@@ -1,12 +1,19 @@
1
1
  package <%= base_package %>.models {
2
- <% if has_manies.length > 0 -%>
2
+ <% if has_manies.length > 0 || has_many_through.length > 0 -%>
3
3
  import org.restfulx.collections.ModelsCollection;
4
4
  <% end -%>
5
+ <% if tree_model.size > 0 -%>
6
+ <% @tree_or_no_tree = 'RxTreeModel' %>
7
+ import org.restfulx.models.RxTreeModel
8
+ <% end -%>
9
+ <% unless tree_model.size > 0 -%>
10
+ <% @tree_or_no_tree = 'RxModel' %>
5
11
  import org.restfulx.models.RxModel;
12
+ <% end -%>
6
13
 
7
14
  [Resource(name="<%= resource_controller_name %>")]
8
15
  [Bindable]
9
- public class <%= class_name %> extends RxModel {
16
+ public class <%= class_name %> extends <%= @tree_or_no_tree %> {
10
17
  <% if attributes && !attributes.empty? && attributes[0].flex_type != "Boolean" -%>
11
18
  public static const LABEL:String = "<%= attributes[0].flex_name %>";
12
19
  <% else -%>
@@ -24,6 +31,25 @@ package <%= base_package %>.models {
24
31
  [BelongsTo]
25
32
  public var <%= model.camelcase(:lower) %>:<%= model.camelcase %>;
26
33
 
34
+ <% end -%>
35
+ <% if tree_model.size > 0 -%>
36
+ [BelongsTo]
37
+ public var <%= tree_model[0].camelcase(:lower) %>:<%= class_name %>;
38
+
39
+ <% end -%>
40
+ <% for model in polymorphic -%>
41
+ [BelongsTo(polymorphic="true", dependsOn="Model1, Model2")]
42
+ public var <%= model.camelcase(:lower) %>:Object;
43
+
44
+ <% end -%>
45
+ <% if has_many_through.size > 0 -%>
46
+ <% has_many_through.each do |k,v| %>
47
+ [HasMany]
48
+ public var <%= k.camelcase(:lower) %>:ModelsCollection;
49
+
50
+ [HasMany(through="<%= k.camelcase %>")]
51
+ public var <%= v.camelcase(:lower) %>:ModelsCollection;
52
+ <% end -%>
27
53
  <% end -%>
28
54
  <% for model in has_ones -%>
29
55
  [HasOne]
@@ -34,6 +60,11 @@ package <%= base_package %>.models {
34
60
  [HasMany]
35
61
  public var <%= model.camelcase(:lower) %>:ModelsCollection;
36
62
 
63
+ <% end -%>
64
+ <% if attachment_field.size > 0 -%>
65
+ [Ignored]
66
+ public var attachmentUrl:String;
67
+
37
68
  <% end -%>
38
69
  public function <%= class_name %>() {
39
70
  super(LABEL);
@@ -1,4 +1,7 @@
1
1
  class <%= class_name %> < ActiveRecord::Base
2
+ <% if distributed -%>
3
+ include RestfulX::UUIDHelper
4
+ <% end -%>
2
5
  <% for model in belongs_tos -%>
3
6
  belongs_to :<%= model %>
4
7
  <% end -%>
@@ -6,6 +9,38 @@ class <%= class_name %> < ActiveRecord::Base
6
9
  has_one :<%= model %>
7
10
  <% end -%>
8
11
  <% for model in has_manies -%>
9
- has_many :<%= model %>
12
+ has_many :<%= model %>, :dependent => :destroy
13
+ <% end -%>
14
+ <% for model in polymorphic -%>
15
+ belongs_to :<%= model %>, :polymorphic => true
16
+ <% end -%>
17
+ <% if has_many_through.size > 0 -%>
18
+ <% has_many_through.each do |k,v| %>
19
+ has_many :<%= k %>
20
+ has_many :<%= v %>, :through => :<%= k %>
21
+ <% end -%>
22
+ <% end -%>
23
+ <% if tree_model.size > 0 -%>
24
+ acts_as_category
25
+ <% end -%>
26
+ <% if attachment_field.size > 0 -%>
27
+ <% if RxSettings.attachment_plugin == 'paperclip' -%>
28
+ # paperclip examples:
29
+ # http://github.com/thoughtbot/paperclip/tree/master
30
+ has_attached_file :<%= attachment_field[0] %>,
31
+ :styles => { :medium => "600x480>", :thumb => "100x100#" }
32
+
33
+ def attachment_url
34
+ <%= attachment_field[0] %>.url(:original)
35
+ end
36
+ <% elsif RxSettings.attachment_plugin == 'attachment_fu' -%>
37
+ # attachment_fu examples:
38
+ # http://github.com/technoweenie/attachment_fu/blob/ab1e4f7b0b9de85e0c9decf061d2ef5c1dc0feaa/README#L56-69
39
+ has_attachment
40
+
41
+ def attachment_url
42
+ "" # FIX ME
43
+ end
44
+ <% end -%>
10
45
  <% end -%>
11
46
  end
@@ -26,14 +26,31 @@ class RxYamlScaffoldGenerator < Rails::Generator::Base
26
26
  line = extract_attrs(line, attrs)
27
27
  end
28
28
  line = model[0].camelcase + " " + line
29
- puts 'running: rx_scaffold ' + line
30
- Rails::Generator::Scripts::Generate.new.run(["rx_scaffold"] + line.split,
31
- :flex_only => options[:flex_only])
32
- puts 'done ...'
33
- sleep 1
29
+
30
+ if ARGV.size > 0
31
+ ARGV.each do |arg|
32
+ if model[0].camelcase == arg
33
+ puts 'running: rx_scaffold ' + line
34
+ Rails::Generator::Scripts::Generate.new.run(["rx_scaffold"] + line.split,
35
+ :flex_only => options[:flex_only],
36
+ :flex_view_only => options[:flex_view_only],
37
+ :rails_only => options[:rails_only])
38
+ puts 'done ...'
39
+ sleep 1
40
+ end
41
+ end
42
+ else
43
+ puts 'running: rx_scaffold ' + line
44
+ Rails::Generator::Scripts::Generate.new.run(["rx_scaffold"] + line.split,
45
+ :flex_only => options[:flex_only],
46
+ :flex_view_only => options[:flex_view_only],
47
+ :rails_only => options[:rails_only])
48
+ puts 'done ...'
49
+ sleep 1
50
+ end
34
51
  end
35
- Rails::Generator::Scripts::Generate.new.run(["rx_config"], :main_only => true,
36
- :skip_framework => options[:skip_framework])
52
+
53
+ Rails::Generator::Scripts::Generate.new.run(["rx_main_app"])
37
54
  end
38
55
  end
39
56
 
@@ -41,9 +58,11 @@ class RxYamlScaffoldGenerator < Rails::Generator::Base
41
58
  def add_options!(opt)
42
59
  opt.separator ''
43
60
  opt.separator 'Options:'
44
- opt.on("--flex-only", "Only generate the Flex/AIR files.",
61
+ opt.on("-f", "--flex-only", "Only generate the Flex/AIR files",
45
62
  "Default: false") { |v| options[:flex_only] = v }
46
- opt.on("--skip-framework", "Don't fetch the latest framework binary. You'll have to link/build the framework yourself.",
47
- "Default: false") { |v| options[:skip_framework] = v }
63
+ opt.on("-r", "--rails-only", "Only generate the Rails files",
64
+ "Default: false") { |v| options[:rails_only] = v }
65
+ opt.on("-fv", "--flex-view-only", "Only generate the Flex component files",
66
+ "Default: false") { |v| options[:flex_view_only] = v }
48
67
  end
49
68
  end
@@ -7,24 +7,26 @@ class RxControllerGenerator < RubiGen::Base
7
7
  :base_folder,
8
8
  :command_controller_name,
9
9
  :model_names,
10
- :command_names
10
+ :command_names,
11
+ :flex_root
11
12
 
12
13
  def initialize(runtime_args, runtime_options = {})
13
14
  super
14
15
  @project_name, @flex_project_name, @command_controller_name,
15
- @base_package, @base_folder = extract_names
16
+ @base_package, @base_folder, @flex_root = extract_names
16
17
 
17
- @model_names = list_as_files("app/flex/#{base_folder}/models")
18
- @command_names = list_as_files("app/flex/#{base_folder}/commands")
18
+ @model_names = list_as_files("#{flex_root}/#{base_folder}/models")
19
+ @command_names = list_as_files("#{flex_root}/#{base_folder}/commands")
19
20
  end
20
21
 
21
22
  def manifest
22
23
  record do |m|
23
- m.template 'controller.as.erb', File.join("app/flex/#{base_folder}/controllers",
24
+ m.template 'controller.as.erb', File.join("#{flex_root}/#{base_folder}/controllers",
24
25
  "#{command_controller_name}.as")
25
26
  if options[:gae]
26
27
  m.file 'restful.py', 'app/controllers/restful.py' if !File.exist?('app/controllers/restful.py')
27
28
  m.file 'assist.py', 'app/models/assist.py' if !File.exist?('app/models/assist.py')
29
+ m.file 'iso8601.py', 'app/models/iso8601.py' if !File.exist?('app/models/iso8601.py')
28
30
  end
29
31
  end
30
32
  end
@@ -23,7 +23,7 @@
23
23
  __author__ = 'Dima Berastau'
24
24
 
25
25
  from google.appengine.ext import db
26
- import datetime
26
+ import datetime, iso8601
27
27
 
28
28
  # Some useful module methods
29
29
  def all(model):
@@ -51,13 +51,13 @@ def update_model_from_params(model, params):
51
51
  elif isinstance(getattr(model, k), int) and v != "":
52
52
  setattr(model, k, int(v))
53
53
  elif isinstance(getattr(model, k), datetime.datetime) and v != "":
54
- value = datetime.datetime.strptime(v, "%Y-%m-%dT%H:%M:%S")
54
+ value = iso8601.parse_date(v)
55
55
  setattr(model, k, value)
56
56
  elif isinstance(getattr(model, k), datetime.date) and v != "":
57
57
  value = datetime.datetime.strptime(v, "%Y-%m-%d")
58
58
  setattr(model, k, datetime.date(value.year, value.month, value.day))
59
59
  elif isinstance(getattr(model, k), datetime.time) and v != "":
60
- value = datetime.datetime.strptime(v, "%Y-%m-%dT%H:%M:%S")
60
+ value = iso8601.parse_date(v)
61
61
  setattr(model, k, datetime.time(value.hour, value.minute, value.second))
62
62
  else:
63
63
  setattr(model, k, v)
@@ -14,8 +14,8 @@ package <%= base_package %>.controllers {
14
14
 
15
15
  public static var commands:Array = [<%= command_names %>]; /* Commands */
16
16
 
17
- public function <%= command_controller_name %>(enforcer:SingletonEnforcer, extraServices:Array,
18
- defaultServiceId:int = -1) {
17
+ public function <%= command_controller_name %>(enforcer:SingletonEnforcer,
18
+ extraServices:Array, defaultServiceId:int = -1) {
19
19
  super(commands, models, extraServices, defaultServiceId);
20
20
  }
21
21
 
@@ -24,11 +24,13 @@ package <%= base_package %>.controllers {
24
24
  return controller;
25
25
  }
26
26
 
27
- public static function initialize(extraServices:Array = null, defaultServiceId:int = -1,
28
- airDatabaseName:String = null):void {
27
+ public static function initialize(extraServices:Array = null,
28
+ defaultServiceId:int = -1, airDatabaseName:String = null):void {
29
29
  if (!RxUtils.isEmpty(airDatabaseName)) Rx.airDatabaseName = airDatabaseName;
30
- controller = new <%= command_controller_name %>(new SingletonEnforcer, extraServices,
31
- defaultServiceId);
30
+ controller = new <%= command_controller_name %>(new SingletonEnforcer,
31
+ extraServices, defaultServiceId);
32
+ Rx.sessionToken = Application.application.parameters.session_token;
33
+ Rx.authenticityToken = Application.application.parameters.authenticity_token;
32
34
  }
33
35
  }
34
36
  }
@@ -0,0 +1,92 @@
1
+ from datetime import datetime, timedelta, tzinfo
2
+ import re
3
+
4
+ __all__ = ["parse_date", "ParseError"]
5
+
6
+ # Adapted from http://delete.me.uk/2005/03/iso8601.html
7
+ ISO8601_REGEX = re.compile(r"(?P<year>[0-9]{4})(-(?P<month>[0-9]{1,2})(-(?P<day>[0-9]{1,2})"
8
+ r"((?P<separator>.)(?P<hour>[0-9]{2}):(?P<minute>[0-9]{2})(:(?P<second>[0-9]{2})(\.(?P<fraction>[0-9]+))?)?"
9
+ r"(?P<timezone>Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?"
10
+ )
11
+ TIMEZONE_REGEX = re.compile("(?P<prefix>[+-])(?P<hours>[0-9]{2}).(?P<minutes>[0-9]{2})")
12
+
13
+ class ParseError(Exception):
14
+ """Raised when there is a problem parsing a date string"""
15
+
16
+ # Yoinked from python docs
17
+ ZERO = timedelta(0)
18
+ class Utc(tzinfo):
19
+ """UTC
20
+
21
+ """
22
+ def utcoffset(self, dt):
23
+ return ZERO
24
+
25
+ def tzname(self, dt):
26
+ return "UTC"
27
+
28
+ def dst(self, dt):
29
+ return ZERO
30
+ UTC = Utc()
31
+
32
+ class FixedOffset(tzinfo):
33
+ """Fixed offset in hours and minutes from UTC
34
+
35
+ """
36
+ def __init__(self, offset_hours, offset_minutes, name):
37
+ self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes)
38
+ self.__name = name
39
+
40
+ def utcoffset(self, dt):
41
+ return self.__offset
42
+
43
+ def tzname(self, dt):
44
+ return self.__name
45
+
46
+ def dst(self, dt):
47
+ return ZERO
48
+
49
+ def __repr__(self):
50
+ return "<FixedOffset %r>" % self.__name
51
+
52
+ def parse_timezone(tzstring, default_timezone=UTC):
53
+ """Parses ISO 8601 time zone specs into tzinfo offsets
54
+
55
+ """
56
+ if tzstring == "Z":
57
+ return default_timezone
58
+ # This isn't strictly correct, but it's common to encounter dates without
59
+ # timezones so I'll assume the default (which defaults to UTC).
60
+ # Addresses issue 4.
61
+ if tzstring is None:
62
+ return default_timezone
63
+ m = TIMEZONE_REGEX.match(tzstring)
64
+ prefix, hours, minutes = m.groups()
65
+ hours, minutes = int(hours), int(minutes)
66
+ if prefix == "-":
67
+ hours = -hours
68
+ minutes = -minutes
69
+ return FixedOffset(hours, minutes, tzstring)
70
+
71
+ def parse_date(datestring, default_timezone=UTC):
72
+ """Parses ISO 8601 dates into datetime objects
73
+
74
+ The timezone is parsed from the date string. However it is quite common to
75
+ have dates without a timezone (not strictly correct). In this case the
76
+ default timezone specified in default_timezone is used. This is UTC by
77
+ default.
78
+ """
79
+ if not isinstance(datestring, basestring):
80
+ raise ParseError("Expecting a string %r" % datestring)
81
+ m = ISO8601_REGEX.match(datestring)
82
+ if not m:
83
+ raise ParseError("Unable to parse date string %r" % datestring)
84
+ groups = m.groupdict()
85
+ tz = parse_timezone(groups["timezone"], default_timezone=default_timezone)
86
+ if groups["fraction"] is None:
87
+ groups["fraction"] = 0
88
+ else:
89
+ groups["fraction"] = int(float("0.%s" % groups["fraction"]) * 1e6)
90
+ return datetime(int(groups["year"]), int(groups["month"]), int(groups["day"]),
91
+ int(groups["hour"]), int(groups["minute"]), int(groups["second"]),
92
+ int(groups["fraction"]), tz)
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Refreshes main Flex/AIR application file to make sure that
3
+ any of the generated components are included. Warning,
4
+ this will wipe your main application file. Used mostly
5
+ during code generation phase.
6
+
7
+ Examples:
8
+ `./script/generate rx_main_app`
@@ -11,11 +11,14 @@ class RxMainAppGenerator < RubiGen::Base
11
11
  :controller_names,
12
12
  :use_air,
13
13
  :use_gae,
14
- :application_tag
14
+ :application_tag,
15
+ :flex_root,
16
+ :distributed
15
17
 
16
18
  def initialize(runtime_args, runtime_options = {})
17
19
  super
18
- @project_name, @flex_project_name, @command_controller_name, @base_package, @base_folder = extract_names
20
+ @project_name, @flex_project_name, @command_controller_name, @base_package, @base_folder,
21
+ @flex_root, @distributed = extract_names
19
22
 
20
23
  project_file_name = APP_ROOT + '/.project'
21
24
  if File.exist?(project_file_name)
@@ -29,8 +32,8 @@ class RxMainAppGenerator < RubiGen::Base
29
32
  end
30
33
 
31
34
  @component_names = []
32
- if File.exists?("app/flex/#{base_folder}/components/generated")
33
- @component_names = list_mxml_files("app/flex/#{base_folder}/components/generated")
35
+ if File.exists?("#{flex_root}/#{base_folder}/components/generated")
36
+ @component_names = list_mxml_files("#{flex_root}/#{base_folder}/components/generated")
34
37
  end
35
38
 
36
39
  @controller_names = []
@@ -43,7 +46,7 @@ class RxMainAppGenerator < RubiGen::Base
43
46
 
44
47
  def manifest
45
48
  record do |m|
46
- m.template 'mainapp.mxml', File.join('app', 'flex', "#{project_name}.mxml")
49
+ m.template 'mainapp.mxml', File.join("#{flex_root}", "#{flex_project_name}.mxml")
47
50
  if options[:gae]
48
51
  m.template 'main.py.erb', 'main.py'
49
52
  end
@@ -56,5 +59,7 @@ class RxMainAppGenerator < RubiGen::Base
56
59
  opt.separator 'Options:'
57
60
  opt.on("--gae", "Generate Google App Engine Python classes in addition to RestfulX Flex resources.",
58
61
  "Default: false") { |v| options[:gae] = v }
62
+ opt.on("--distributed", "Creates migrations, controllers and models that use UUIDs and are distribution ready",
63
+ "Default: false") { |v| options[:distributed] = v }
59
64
  end
60
65
  end