restfulx 1.2.1 → 1.2.2

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 (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