dima-restfulx 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/Rakefile +4 -2
- data/VERSION.yml +1 -1
- data/app_generators/rx_app/rx_app_generator.rb +2 -2
- data/app_generators/rx_app/templates/actionscript.properties +1 -1
- data/app_generators/rx_app/templates/actionscriptair.properties +1 -1
- data/app_generators/rx_app/templates/mainapp-config.xml +1 -0
- data/app_generators/rx_app/templates/mainapp.mxml +19 -3
- data/app_generators/rx_app/templates/restfulx.yml +9 -24
- data/bin/rx-gen +1 -1
- data/lib/restfulx/active_foo.rb +5 -3
- data/lib/restfulx/active_record_tasks.rb +1 -2
- data/lib/restfulx/active_record_uuid_helper.rb +17 -0
- data/lib/restfulx/configuration.rb +20 -26
- data/lib/restfulx/{schema_to_yaml → rails/schema_to_yaml}/extensions/enumerable.rb +1 -0
- data/lib/restfulx/{schema_to_yaml → rails/schema_to_yaml}/settings/config.rb +1 -0
- data/lib/restfulx/{schema_to_yaml → rails/schema_to_yaml}/settings/core.rb +4 -1
- data/lib/restfulx/{schema_to_yaml.rb → rails/schema_to_yaml.rb} +2 -12
- data/lib/restfulx/rails/swf_helper.rb +7 -8
- data/lib/restfulx/tasks.rb +0 -1
- data/lib/restfulx.rb +2 -10
- data/rails_generators/rx_config/rx_config_generator.rb +20 -9
- data/rails_generators/rx_config/templates/actionscript.properties +1 -1
- data/rails_generators/rx_config/templates/actionscriptair.properties +1 -1
- data/rails_generators/rx_config/templates/mainapp-config.xml +1 -0
- data/rails_generators/rx_config/templates/restfulx.erb +46 -10
- data/rails_generators/rx_config/templates/restfulx.yml +9 -5
- data/rails_generators/rx_config/templates/session_store_flash.erb +1 -0
- data/rails_generators/rx_main_app/rx_main_app_generator.rb +2 -2
- data/rails_generators/rx_main_app/templates/mainapp.mxml +1 -1
- data/rails_generators/rx_scaffold/rx_scaffold_generator.rb +16 -7
- data/rails_generators/rx_scaffold/templates/controllers/resource_controller.rb.erb +2 -2
- data/rails_generators/rx_scaffold/templates/functional_test.rb +45 -0
- data/rails_generators/rx_scaffold/templates/helper_test.rb +4 -0
- data/rails_generators/rx_scaffold/templates/layouts/default.erb +7 -5
- data/rails_generators/rx_scaffold/templates/migration.rb.erb +4 -4
- data/rxgen_generators/rx_config/rx_config_generator.rb +2 -0
- data/rxgen_generators/rx_controller/rx_controller_generator.rb +1 -0
- data/rxgen_generators/rx_controller/templates/assist.py +4 -4
- data/rxgen_generators/rx_controller/templates/iso8601.py +92 -0
- data/rxgen_generators/rx_main_app/rx_main_app_generator.rb +2 -2
- data/rxgen_generators/rx_main_app/templates/mainapp.mxml +19 -3
- data/rxgen_generators/rx_scaffold/rx_scaffold_generator.rb +57 -10
- data/rxgen_generators/rx_scaffold/templates/{component.mxml.erb → layouts/default.erb} +56 -10
- data/rxgen_generators/rx_scaffold/templates/model.as.erb +33 -2
- data/spec/restfulx_spec.rb +1 -4
- data/spec/spec_helper.rb +0 -3
- data/tasks/restfulx.rake +2 -0
- data/test/rails/helpers/functional_test_helper.rb +1 -1
- data/test/rails/helpers/test_helper.rb +1 -8
- data/test/rails/helpers/unit_test_helper.rb +2 -3
- data/test/rails/test_active_foo.rb +1 -1
- data/test/rails/test_rails_integration_functional.rb +1 -1
- data/test/rails/test_to_fxml.rb +1 -1
- data/test/rails/test_to_json.rb +1 -1
- metadata +60 -75
- data/lib/restfulx/uuid_helper.rb +0 -15
- /data/test/rails/controllers/{application.rb → application_controller.rb} +0 -0
@@ -1,12 +1,47 @@
|
|
1
|
-
#
|
2
|
-
# which
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
# the following patches allow us to overwrite session key on file uploads from Flash,
|
2
|
+
# which ends up creating a new session for every File.upload() invocation.
|
3
|
+
|
4
|
+
<% if RAILS_GEM_VERSION =~ /^2.3/ -%>
|
5
|
+
require 'rack/utils'
|
6
|
+
|
7
|
+
class FlashSessionCookieMiddleware
|
8
|
+
def initialize(app, session_key = '_session_id')
|
9
|
+
@app = app
|
10
|
+
@session_key = session_key
|
11
|
+
@session_token = "_session_id"
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
|
16
|
+
params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
|
17
|
+
env['HTTP_COOKIE'] = [ @session_key, params[@session_token] ].join('=').freeze unless params[@session_token].nil?
|
18
|
+
end
|
19
|
+
@app.call(env)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class FlexNestedAttributeMiddleware
|
24
|
+
def initialize(app)
|
25
|
+
@app = app
|
26
|
+
end
|
27
|
+
|
28
|
+
def call(env)
|
29
|
+
req = Rack::Request.new(env)
|
30
|
+
if req && req.path_info =~ /\.fxml$/
|
31
|
+
if req.put? || req.post? || req.delete?
|
32
|
+
req.params.each do |key,value|
|
33
|
+
value.select { |k,v| k =~ /\_attributes$/ }.each do |match|
|
34
|
+
env['rack.request.form_hash'][key][match[0]] = ActiveSupport::JSON.decode(match[1])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
@app.call(env)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
ActionController::Dispatcher.middleware.insert_after 'ActionController::ParamsParser', FlexNestedAttributeMiddleware
|
44
|
+
<% else -%>
|
10
45
|
class CGI::Session
|
11
46
|
alias original_initialize initialize
|
12
47
|
|
@@ -27,6 +62,7 @@ class CGI::Session
|
|
27
62
|
return option
|
28
63
|
end
|
29
64
|
end
|
65
|
+
<% end -%>
|
30
66
|
|
31
67
|
# If you have configured your Rails/Flex/AIR application to share authenticity_token
|
32
68
|
# comment this out to enable forgery protection. By default, this is disabled to allow
|
@@ -35,5 +71,5 @@ ActionController::Base.allow_forgery_protection = false
|
|
35
71
|
|
36
72
|
<% if distributed -%>
|
37
73
|
# If we are in distributed mode we need to make sure that the RestfulX::UUIDHelper is loaded
|
38
|
-
require "restfulx/
|
74
|
+
require "restfulx/active_record_uuid_helper"
|
39
75
|
<% end -%>
|
@@ -2,22 +2,22 @@
|
|
2
2
|
|
3
3
|
# This option controls what the main Flex application file will be called.
|
4
4
|
# By default it will be equal to the name of your rails project camelized
|
5
|
-
|
5
|
+
project_name: <%= project_name %>
|
6
6
|
|
7
7
|
# This options determines what the root folder for generated Flex code is.
|
8
8
|
# By default 'app/flex'
|
9
|
-
|
9
|
+
flex_root: <%= flex_root %>
|
10
10
|
|
11
11
|
# By default flex models, commands, controllers and components are genearated into
|
12
12
|
# <flex-root>/<your rails project name> folder. If you'd like to customize the target folder
|
13
13
|
# (to say append a "com" package before your rails project name) uncomment the line below
|
14
14
|
# base-package must follow the usual flex package notation (a string separated by ".")
|
15
|
-
|
15
|
+
base_package: <%= base_package %>
|
16
16
|
|
17
17
|
# Main RestfulX controller is typically named AppicationController. This controller is created in
|
18
18
|
# <base-package>.controllers folder. You can customize the name by uncommenting the following line
|
19
19
|
# and changing the controller name.
|
20
|
-
|
20
|
+
controller_name: <%= command_controller_name %>
|
21
21
|
|
22
22
|
# If you are using Rails on the back-end and Adobe AIR as the client you can generate Rails/Flex/AIR
|
23
23
|
# code to take advantage of synchronization (online/offline) support in RestfulX by changing the following
|
@@ -35,17 +35,21 @@ defaults: &defaults
|
|
35
35
|
tables: [table1 table2]
|
36
36
|
fields: [field1 field2]
|
37
37
|
|
38
|
+
# set up specific options for development environment
|
38
39
|
development:
|
39
40
|
<<: *defaults
|
40
41
|
|
42
|
+
# set up specific options for test environment
|
41
43
|
test:
|
42
44
|
<<: *defaults
|
43
45
|
|
46
|
+
# set up specific options for production environment
|
44
47
|
production:
|
45
48
|
<<: *defaults
|
46
49
|
|
47
|
-
#
|
50
|
+
# The following special model.yml fields are supported.
|
48
51
|
#
|
52
|
+
# For example:
|
49
53
|
# attachment_field: [avatar]
|
50
54
|
# * arg takes Paperclip field name, or takes [uploaded_data] for Attachment_Fu
|
51
55
|
# belongs_to: [account, profile]
|
@@ -0,0 +1 @@
|
|
1
|
+
ActionController::Dispatcher.middleware.use FlashSessionCookieMiddleware, ActionController::Base.session_options[:key]
|
@@ -43,8 +43,8 @@ class RxMainAppGenerator < Rails::Generator::Base
|
|
43
43
|
end
|
44
44
|
|
45
45
|
@component_names = []
|
46
|
-
if File.exists?("#{flex_root}/#{base_folder}/
|
47
|
-
@component_names = list_mxml_files("#{flex_root}/#{base_folder}/
|
46
|
+
if File.exists?("#{flex_root}/#{base_folder}/views/generated")
|
47
|
+
@component_names = list_mxml_files("#{flex_root}/#{base_folder}/views/generated")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
2
2
|
<mx:<%= application_tag %> xmlns:mx="http://www.adobe.com/2006/mxml"
|
3
|
-
xmlns:generated="<%= base_package %>.
|
3
|
+
xmlns:generated="<%= base_package %>.views.generated.*"
|
4
4
|
paddingBottom="8" paddingLeft="8" paddingRight="8" paddingTop="8"
|
5
5
|
layout="horizontal" styleName="plain" initialize="init()">
|
6
6
|
<mx:Script>
|
@@ -125,7 +125,7 @@ class RxScaffoldGenerator < Rails::Generator::NamedBase
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def manifest
|
128
|
-
record do |m|
|
128
|
+
record do |m|
|
129
129
|
unless options[:flex_view_only]
|
130
130
|
m.template 'model.as.erb',
|
131
131
|
File.join("#{@flex_root}", base_folder, "models", "#{@class_name}.as"),
|
@@ -139,11 +139,11 @@ class RxScaffoldGenerator < Rails::Generator::NamedBase
|
|
139
139
|
|
140
140
|
if @layout.size > 0
|
141
141
|
m.template "layouts/#{@layout}.erb",
|
142
|
-
File.join("#{@flex_root}", base_folder, "
|
142
|
+
File.join("#{@flex_root}", base_folder, "views", "generated", "#{@class_name}Box.mxml"),
|
143
143
|
:assigns => { :resource_controller_name => "#{file_name.pluralize}" }
|
144
144
|
else
|
145
145
|
m.template "layouts/#{RxSettings.layouts.default}.erb",
|
146
|
-
File.join("#{@flex_root}", base_folder, "
|
146
|
+
File.join("#{@flex_root}", base_folder, "views", "generated", "#{@class_name}Box.mxml"),
|
147
147
|
:assigns => { :resource_controller_name => "#{file_name.pluralize}" }
|
148
148
|
end
|
149
149
|
|
@@ -155,11 +155,20 @@ class RxScaffoldGenerator < Rails::Generator::NamedBase
|
|
155
155
|
unless options[:skip_migration]
|
156
156
|
FileUtils.rm Dir.glob("db/migrate/[0-9]*_create_#{file_path.gsub(/\//, '_').pluralize}.rb"), :force => true
|
157
157
|
m.migration_template 'migration.rb.erb', 'db/migrate', :assigns => {
|
158
|
-
:migration_name => "Create#{
|
158
|
+
:migration_name => "Create#{file_path.gsub(/\//, '_').pluralize.camelcase.gsub(/::/, '')}"
|
159
159
|
}, :migration_file_name => "create_#{file_path.gsub(/\//, '_').pluralize}" unless options[:flex_only]
|
160
160
|
end
|
161
|
-
|
162
|
-
m.
|
161
|
+
|
162
|
+
m.directory(File.join('test/functional', controller_class_path))
|
163
|
+
m.directory(File.join('test/unit', class_path))
|
164
|
+
m.directory(File.join('test/unit/helpers', class_path))
|
165
|
+
|
166
|
+
m.template('functional_test.rb', File.join('test/functional', controller_class_path, "#{controller_file_name}_controller_test.rb"))
|
167
|
+
m.template('helper_test.rb', File.join('test/unit/helpers', controller_class_path, "#{controller_file_name}_helper_test.rb"))
|
168
|
+
|
169
|
+
if File.open('config/routes.rb').grep(/^\s*map.resources :#{controller_file_name}/).empty?
|
170
|
+
m.route_resources controller_file_name
|
171
|
+
end
|
163
172
|
|
164
173
|
m.dependency 'rx_controller', [name] + @args, :collision => :force
|
165
174
|
end
|
@@ -230,4 +239,4 @@ class RxScaffoldGenerator < Rails::Generator::NamedBase
|
|
230
239
|
opt.on("-fv", "--flex-view-only", "Only generate the Flex component files",
|
231
240
|
"Default: false") { |v| options[:flex_view_only] = v }
|
232
241
|
end
|
233
|
-
end
|
242
|
+
end
|
@@ -10,8 +10,8 @@ class <%= controller_class_name %>Controller < ResourceController::Base
|
|
10
10
|
update.failure.wants.fxml { render :fxml => @object.errors }
|
11
11
|
destroy.wants.fxml { render :fxml => @object }
|
12
12
|
|
13
|
-
private
|
14
|
-
|
13
|
+
private
|
14
|
+
|
15
15
|
def collection
|
16
16
|
@collection = end_of_association_chain.all
|
17
17
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class <%= controller_class_name %>ControllerTest < ActionController::TestCase
|
4
|
+
test "should get index" do
|
5
|
+
get :index
|
6
|
+
assert_response :success
|
7
|
+
assert_not_nil assigns(:<%= table_name %>)
|
8
|
+
end
|
9
|
+
|
10
|
+
test "should get new" do
|
11
|
+
get :new
|
12
|
+
assert_response :success
|
13
|
+
end
|
14
|
+
|
15
|
+
test "should create <%= file_name %>" do
|
16
|
+
assert_difference('<%= class_name %>.count') do
|
17
|
+
post :create, :<%= file_name %> => { }
|
18
|
+
end
|
19
|
+
|
20
|
+
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
|
21
|
+
end
|
22
|
+
|
23
|
+
test "should show <%= file_name %>" do
|
24
|
+
get :show, :id => <%= table_name %>(:one).id
|
25
|
+
assert_response :success
|
26
|
+
end
|
27
|
+
|
28
|
+
test "should get edit" do
|
29
|
+
get :edit, :id => <%= table_name %>(:one).id
|
30
|
+
assert_response :success
|
31
|
+
end
|
32
|
+
|
33
|
+
test "should update <%= file_name %>" do
|
34
|
+
put :update, :id => <%= table_name %>(:one).id, :<%= file_name %> => { }
|
35
|
+
assert_redirected_to <%= file_name %>_path(assigns(:<%= file_name %>))
|
36
|
+
end
|
37
|
+
|
38
|
+
test "should destroy <%= file_name %>" do
|
39
|
+
assert_difference('<%= class_name %>.count', -1) do
|
40
|
+
delete :destroy, :id => <%= table_name %>(:one).id
|
41
|
+
end
|
42
|
+
|
43
|
+
assert_redirected_to <%= table_name %>_path
|
44
|
+
end
|
45
|
+
end
|
@@ -9,12 +9,14 @@
|
|
9
9
|
import <%= base_package %>.models.<%= model.camelcase %>;
|
10
10
|
<% end -%>
|
11
11
|
<% if attachment_field.size > 0 -%>
|
12
|
+
import flash.net.FileReference;
|
12
13
|
import org.restfulx.utils.RxFileReference;
|
13
14
|
<% end -%>
|
14
15
|
|
15
16
|
[Bindable]
|
16
17
|
private var <%= class_name.dcfirst %>:<%= class_name %> = new <%= class_name %>();
|
17
18
|
<% if attachment_field.size > 0 -%>
|
19
|
+
|
18
20
|
[Bindable]
|
19
21
|
private var fileName:String = "None selected";
|
20
22
|
|
@@ -83,10 +85,10 @@
|
|
83
85
|
|
84
86
|
private function chooseFile():void {
|
85
87
|
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();
|
88
|
+
file.reference.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler, false, 0, true);
|
89
|
+
file.reference.addEventListener(Event.SELECT, selectFile, false, 0, true);
|
90
|
+
file.reference.addEventListener(Event.CANCEL, cancelBrowse, false, 0, true);
|
91
|
+
file.reference.browse();
|
90
92
|
}
|
91
93
|
|
92
94
|
private function selectFile(event:Event):void {
|
@@ -98,7 +100,7 @@
|
|
98
100
|
}
|
99
101
|
|
100
102
|
private function fileSelected(event:Event):void {
|
101
|
-
fileName =
|
103
|
+
fileName = FileReference(event.target).name;
|
102
104
|
}
|
103
105
|
|
104
106
|
private function ioErrorHandler(event:Event):void {
|
@@ -19,10 +19,10 @@ class <%= migration_name %> < ActiveRecord::Migration
|
|
19
19
|
<% if attachment_field.size > 0 -%>
|
20
20
|
<% if RxSettings.attachment_plugin == 'paperclip' -%>
|
21
21
|
# For paperclip
|
22
|
-
t.column
|
23
|
-
t.column
|
24
|
-
t.column
|
25
|
-
t.column
|
22
|
+
t.column :<%= attachment_field[0] %>_file_name, :string
|
23
|
+
t.column :<%= attachment_field[0] %>_content_type, :string
|
24
|
+
t.column :<%= attachment_field[0] %>_file_size, :integer
|
25
|
+
t.column :<%= attachment_field[0] %>_updated_at, :datetime
|
26
26
|
<% elsif RxSettings.attachment_plugin == 'attachment_fu' -%>
|
27
27
|
# For attachment_fu
|
28
28
|
t.column :parent_id, :integer
|
@@ -26,6 +26,7 @@ class RxControllerGenerator < RubiGen::Base
|
|
26
26
|
if options[:gae]
|
27
27
|
m.file 'restful.py', 'app/controllers/restful.py' if !File.exist?('app/controllers/restful.py')
|
28
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')
|
29
30
|
end
|
30
31
|
end
|
31
32
|
end
|
@@ -23,11 +23,11 @@
|
|
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):
|
30
|
-
items = "".join(str(item.to_xml()) for item in model.all())
|
30
|
+
items = "".join(str(item.to_xml().encode('UTF-8')) for item in model.all())
|
31
31
|
if items == "":
|
32
32
|
return '<entities type="array"/>'
|
33
33
|
else:
|
@@ -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 =
|
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 =
|
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)
|
@@ -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)
|
@@ -32,8 +32,8 @@ class RxMainAppGenerator < RubiGen::Base
|
|
32
32
|
end
|
33
33
|
|
34
34
|
@component_names = []
|
35
|
-
if File.exists?("#{flex_root}/#{base_folder}/
|
36
|
-
@component_names = list_mxml_files("#{flex_root}/#{base_folder}/
|
35
|
+
if File.exists?("#{flex_root}/#{base_folder}/views/generated")
|
36
|
+
@component_names = list_mxml_files("#{flex_root}/#{base_folder}/views/generated")
|
37
37
|
end
|
38
38
|
|
39
39
|
@controller_names = []
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<?xml version="1.0" encoding="utf-8"?>
|
2
2
|
<mx:<%= application_tag %> xmlns:mx="http://www.adobe.com/2006/mxml"
|
3
|
-
xmlns:generated="<%= base_package %>.
|
3
|
+
xmlns:generated="<%= base_package %>.views.generated.*"
|
4
4
|
paddingBottom="8" paddingLeft="8" paddingRight="8" paddingTop="8"
|
5
5
|
layout="horizontal" styleName="plain" initialize="init()">
|
6
6
|
<mx:Script>
|
@@ -14,12 +14,13 @@
|
|
14
14
|
import org.restfulx.events.PushStartEvent;
|
15
15
|
import org.restfulx.controllers.ChangeController;
|
16
16
|
import org.restfulx.services.ISyncingServiceProvider;
|
17
|
-
import org.restfulx.services.http.XMLHTTPServiceProvider;
|
18
17
|
<% end -%>
|
19
18
|
import org.restfulx.services.air.AIRServiceProvider;
|
20
19
|
<% end -%>
|
21
20
|
<% if use_gae -%>
|
22
21
|
import org.restfulx.services.http.GAEHTTPServiceProvider;
|
22
|
+
<% else -%>
|
23
|
+
import org.restfulx.services.http.XMLHTTPServiceProvider;
|
23
24
|
<% end -%>
|
24
25
|
import org.restfulx.Rx;
|
25
26
|
import <%= base_package %>.controllers.<%= command_controller_name %>;
|
@@ -53,9 +54,15 @@
|
|
53
54
|
AIRServiceProvider.ID, "<%= base_package %>");
|
54
55
|
<% if distributed -%>
|
55
56
|
|
57
|
+
<% if use_gae -%>
|
58
|
+
Rx.changes.setSyncProviders(
|
59
|
+
ISyncingServiceProvider(Rx.services.getServiceProvider(AIRServiceProvider.ID)),
|
60
|
+
Rx.services.getServiceProvider(GAEHTTPServiceProvider.ID));
|
61
|
+
<% else -%>
|
56
62
|
Rx.changes.setSyncProviders(
|
57
63
|
ISyncingServiceProvider(Rx.services.getServiceProvider(AIRServiceProvider.ID)),
|
58
64
|
Rx.services.getServiceProvider(XMLHTTPServiceProvider.ID));
|
65
|
+
<% end -%>
|
59
66
|
|
60
67
|
Rx.changes.addEventListener(PushStartEvent.ID, onPushStart);
|
61
68
|
Rx.changes.addEventListener(PushEndEvent.ID, onPushEnd);
|
@@ -93,7 +100,11 @@
|
|
93
100
|
online = (socketMonitor.available) ? true : false;
|
94
101
|
|
95
102
|
if (online) {
|
103
|
+
<% if use_gae -%>
|
104
|
+
Rx.defaultServiceId = GAEHTTPServiceProvider.ID;
|
105
|
+
<% else -%>
|
96
106
|
Rx.defaultServiceId = XMLHTTPServiceProvider.ID;
|
107
|
+
<% end -%>
|
97
108
|
} else {
|
98
109
|
Rx.defaultServiceId = AIRServiceProvider.ID;
|
99
110
|
}
|
@@ -101,8 +112,13 @@
|
|
101
112
|
|
102
113
|
private function getCurrentProviderName(id:int):String {
|
103
114
|
switch (id) {
|
115
|
+
<% if use_gae -%>
|
116
|
+
case GAEHTTPServiceProvider.ID:
|
117
|
+
return "GAE";
|
118
|
+
<% else -%>
|
104
119
|
case XMLHTTPServiceProvider.ID:
|
105
|
-
return "
|
120
|
+
return "XML/HTTP";
|
121
|
+
<% end -%>
|
106
122
|
case AIRServiceProvider.ID:
|
107
123
|
return "AIR (SQLite)";
|
108
124
|
default :
|
@@ -70,7 +70,14 @@ class RxScaffoldGenerator < RubiGen::Base
|
|
70
70
|
|
71
71
|
attr_reader :belongs_tos,
|
72
72
|
:has_manies,
|
73
|
-
:has_ones
|
73
|
+
:has_ones,
|
74
|
+
:attachment_field,
|
75
|
+
:has_many_through,
|
76
|
+
:polymorphic,
|
77
|
+
:tree_model,
|
78
|
+
:layout,
|
79
|
+
:ignored_fields,
|
80
|
+
:args_for_generation
|
74
81
|
|
75
82
|
attr_reader :name,
|
76
83
|
:class_name,
|
@@ -93,14 +100,20 @@ class RxScaffoldGenerator < RubiGen::Base
|
|
93
100
|
end
|
94
101
|
|
95
102
|
def manifest
|
96
|
-
record do |m|
|
103
|
+
record do |m|
|
97
104
|
m.template 'model.as.erb',
|
98
105
|
File.join("#{flex_root}", base_folder, "models", "#{@class_name}.as"),
|
99
106
|
:assigns => { :resource_controller_name => "#{file_name.pluralize}" }
|
100
107
|
|
101
|
-
|
102
|
-
|
103
|
-
|
108
|
+
if @layout.size > 0
|
109
|
+
m.template "layouts/#{@layout}.erb",
|
110
|
+
File.join("#{@flex_root}", base_folder, "views", "generated", "#{@class_name}Box.mxml"),
|
111
|
+
:assigns => { :resource_controller_name => "#{file_name.pluralize}" }
|
112
|
+
else
|
113
|
+
m.template "layouts/#{RxSettings.layouts.default}.erb",
|
114
|
+
File.join("#{@flex_root}", base_folder, "views", "generated", "#{@class_name}Box.mxml"),
|
115
|
+
:assigns => { :resource_controller_name => "#{file_name.pluralize}" }
|
116
|
+
end
|
104
117
|
|
105
118
|
if options[:gae]
|
106
119
|
m.template 'controller.py.erb', "app/controllers/#{file_name.pluralize}.py"
|
@@ -113,23 +126,57 @@ class RxScaffoldGenerator < RubiGen::Base
|
|
113
126
|
|
114
127
|
protected
|
115
128
|
def extract_relationships
|
129
|
+
# arrays
|
116
130
|
@belongs_tos = []
|
117
131
|
@has_ones = []
|
118
132
|
@has_manies = []
|
119
|
-
|
133
|
+
@attachment_field = []
|
134
|
+
@polymorphic = []
|
135
|
+
@tree_model = []
|
136
|
+
@layout = []
|
137
|
+
@ignored_fields = []
|
138
|
+
|
139
|
+
# hashes
|
140
|
+
@has_many_through = {}
|
141
|
+
|
120
142
|
@args.each do |arg|
|
143
|
+
# arrays
|
121
144
|
if arg =~ /^has_one:/
|
122
|
-
# arg = "has_one:arg1,arg2", so all the has_one are together
|
123
145
|
@has_ones = arg.split(':')[1].split(',')
|
124
146
|
elsif arg =~ /^has_many:/
|
125
|
-
# arg = "has_many:arg1,arg2", so all the has_many are together
|
126
147
|
@has_manies = arg.split(":")[1].split(",")
|
127
|
-
elsif arg =~ /^belongs_to:/
|
148
|
+
elsif arg =~ /^belongs_to:/
|
128
149
|
@belongs_tos = arg.split(":")[1].split(',')
|
150
|
+
elsif arg =~ /^attachment_field:/
|
151
|
+
@attachment_field = arg.split(":")[1].split(',')
|
152
|
+
elsif arg =~ /^polymorphic:/
|
153
|
+
@polymorphic = arg.split(":")[1].split(',')
|
154
|
+
elsif arg =~ /^tree_model:/
|
155
|
+
@tree_model = arg.split(":")[1].split(',')
|
156
|
+
elsif arg =~ /^layout:/
|
157
|
+
@layout = arg.split(":")[1].split(',')
|
158
|
+
elsif arg =~ /^ignored_fields:/
|
159
|
+
@ignored_fields = arg.split(":")[1].split(',')
|
160
|
+
# hashes
|
161
|
+
elsif arg =~ /^has_many_through:/
|
162
|
+
hmt_arr = arg.split(":")[1].split(',')
|
163
|
+
@has_many_through[hmt_arr.first] = hmt_arr.last
|
129
164
|
end
|
130
165
|
end
|
131
166
|
|
132
|
-
|
167
|
+
# delete special fields from @args ivar
|
168
|
+
%w(has_one has_many belongs_to attachment_field has_many_through
|
169
|
+
polymorphic tree_model layout ignored_fields).each do |special_field|
|
170
|
+
@args.delete_if { |f| f =~ /^(#{special_field}):/ }
|
171
|
+
end
|
172
|
+
|
173
|
+
@args_for_generation = @args.clone
|
174
|
+
|
175
|
+
# delete ignored_fields from @args ivar
|
176
|
+
@ignored_fields.each do |ignored|
|
177
|
+
@args.delete_if { |f| f =~ /^(#{ignored}):/ }
|
178
|
+
end
|
179
|
+
|
133
180
|
end
|
134
181
|
|
135
182
|
def attributes
|