my_enginery 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.travis.yml +9 -0
- data/CHANGELOG.md +14 -0
- data/Gemfile +12 -0
- data/LICENSE +19 -0
- data/README.md +957 -0
- data/Rakefile +48 -0
- data/app/base/.pryrc +1 -0
- data/app/base/Gemfile +25 -0
- data/app/base/Rakefile +4 -0
- data/app/base/app.rb +8 -0
- data/app/base/base/boot.rb +45 -0
- data/app/base/base/config.rb +127 -0
- data/app/base/base/controllers/rear-controllers/.gitkeep +0 -0
- data/app/base/base/database.rb +3 -0
- data/app/base/base/helpers/application_helpers.rb +3 -0
- data/app/base/base/migrations/.gitkeep +0 -0
- data/app/base/base/models/.gitkeep +0 -0
- data/app/base/base/specs/.gitkeep +0 -0
- data/app/base/base/views/.gitkeep +0 -0
- data/app/base/config.ru +4 -0
- data/app/base/config/config.yml +17 -0
- data/app/base/public/assets/Enginery.png +0 -0
- data/app/base/public/assets/Espresso.png +0 -0
- data/app/base/public/assets/application.css +13 -0
- data/app/base/public/assets/application.js +2 -0
- data/app/base/public/assets/bootstrap/css/bootstrap-responsive.min.css +9 -0
- data/app/base/public/assets/bootstrap/css/bootstrap.min.css +9 -0
- data/app/base/public/assets/bootstrap/img/glyphicons-halflings-white.png +0 -0
- data/app/base/public/assets/bootstrap/img/glyphicons-halflings.png +0 -0
- data/app/base/public/assets/bootstrap/js/bootstrap.min.js +6 -0
- data/app/base/public/assets/jquery.js +6 -0
- data/app/base/var/db/.gitkeep +0 -0
- data/app/base/var/log/.gitkeep +0 -0
- data/app/base/var/pid/.gitkeep +0 -0
- data/app/database/ActiveRecord.rb +11 -0
- data/app/database/DataMapper.rb +11 -0
- data/app/database/Sequel.rb +11 -0
- data/app/database/mysql.yml +24 -0
- data/app/database/postgres.yml +24 -0
- data/app/database/sqlite.yml +24 -0
- data/app/gemfiles/ActiveRecord.rb +1 -0
- data/app/gemfiles/BlueCloth.rb +1 -0
- data/app/gemfiles/DataMapper.rb +1 -0
- data/app/gemfiles/FastCGI.rb +1 -0
- data/app/gemfiles/Puma.rb +1 -0
- data/app/gemfiles/RDiscount.rb +1 -0
- data/app/gemfiles/RDoc.rb +1 -0
- data/app/gemfiles/RedCloth.rb +1 -0
- data/app/gemfiles/WEBrick.rb +1 -0
- data/app/gemfiles/WikiCloth.rb +1 -0
- data/app/gemfiles/mysql/ActiveRecord.rb +1 -0
- data/app/gemfiles/mysql/DataMapper.rb +1 -0
- data/app/gemfiles/mysql/Sequel.rb +1 -0
- data/app/gemfiles/postgres/ActiveRecord.rb +1 -0
- data/app/gemfiles/postgres/DataMapper.rb +1 -0
- data/app/gemfiles/postgres/Sequel.rb +1 -0
- data/app/gemfiles/sqlite/ActiveRecord.rb +1 -0
- data/app/gemfiles/sqlite/DataMapper.rb +1 -0
- data/app/gemfiles/sqlite/Sequel.rb +1 -0
- data/app/layouts/ERB/layout.erb +56 -0
- data/app/layouts/Erubis/layout.erb +56 -0
- data/app/layouts/Haml/layout.haml +38 -0
- data/app/layouts/Slim/layout.slim +38 -0
- data/app/migrations/ActiveRecord.erb +51 -0
- data/app/migrations/DataMapper.erb +61 -0
- data/app/migrations/Sequel.erb +54 -0
- data/app/migrations/tracking_table/ActiveRecord.rb +19 -0
- data/app/migrations/tracking_table/DataMapper.rb +26 -0
- data/app/migrations/tracking_table/Sequel.rb +18 -0
- data/app/rakefiles/ActiveRecord.rb +0 -0
- data/app/rakefiles/DataMapper.rb +1 -0
- data/app/rakefiles/Sequel.rb +0 -0
- data/app/rakefiles/Specular.rb +1 -0
- data/app/specfiles/Specular.erb +7 -0
- data/bin/my_enginery +235 -0
- data/lib/enginery.rb +23 -0
- data/lib/enginery/cli.rb +44 -0
- data/lib/enginery/configurator.rb +139 -0
- data/lib/enginery/delete.rb +116 -0
- data/lib/enginery/enginery.rb +41 -0
- data/lib/enginery/generator.rb +325 -0
- data/lib/enginery/helpers/app.rb +83 -0
- data/lib/enginery/helpers/generic.rb +145 -0
- data/lib/enginery/helpers/input.rb +123 -0
- data/lib/enginery/helpers/orm.rb +86 -0
- data/lib/enginery/helpers/validations.rb +101 -0
- data/lib/enginery/migrator.rb +371 -0
- data/lib/enginery/rake-tasks/data_mapper.rb +49 -0
- data/lib/enginery/rake-tasks/specular.rb +41 -0
- data/lib/enginery/registry.rb +101 -0
- data/lib/enginery/usage.rb +66 -0
- data/lib/enginery/version.rb +7 -0
- data/logo.png +0 -0
- data/my_enginery.gemspec +37 -0
- data/test/delete/test__admin.rb +49 -0
- data/test/delete/test__controller.rb +37 -0
- data/test/delete/test__helper.rb +49 -0
- data/test/delete/test__migration.rb +27 -0
- data/test/delete/test__model.rb +35 -0
- data/test/delete/test__route.rb +35 -0
- data/test/delete/test__spec.rb +59 -0
- data/test/delete/test__view.rb +51 -0
- data/test/generator/test__admin.rb +39 -0
- data/test/generator/test__controller.rb +123 -0
- data/test/generator/test__helper.rb +56 -0
- data/test/generator/test__model.rb +206 -0
- data/test/generator/test__project.rb +81 -0
- data/test/generator/test__route.rb +110 -0
- data/test/generator/test__spec.rb +56 -0
- data/test/generator/test__view.rb +85 -0
- data/test/migrator/test__auto_generation.rb +41 -0
- data/test/migrator/test__manual_generation.rb +59 -0
- data/test/migrator/test__migrations.rb +139 -0
- data/test/sandbox/.gitkeep +0 -0
- data/test/setup.rb +29 -0
- data/test/support/spec_helpers.rb +151 -0
- metadata +392 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
module Enginery
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def load_file file
|
5
|
+
pv, $VERBOSE = $VERBOSE, nil
|
6
|
+
load file
|
7
|
+
ensure
|
8
|
+
$VERBOSE = pv
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_boot_rb
|
12
|
+
orig = Array.new($:)
|
13
|
+
load_file dst_path.boot_rb
|
14
|
+
ensure
|
15
|
+
# for some reason, Bundler get rid of existing loadpath entries.
|
16
|
+
# usually this will break autoloading, so storing orig paths and inserting them back
|
17
|
+
orig.each {|p| $:.include?(p) || $: << p}
|
18
|
+
end
|
19
|
+
|
20
|
+
def boot_app
|
21
|
+
load_boot_rb
|
22
|
+
App.boot!
|
23
|
+
end
|
24
|
+
|
25
|
+
def app_controllers
|
26
|
+
App.mounted_controllers.select {|c| controller_exists?(c.name)}
|
27
|
+
end
|
28
|
+
|
29
|
+
def routes_by_controller controller
|
30
|
+
Dir[dst_path(:controllers, class_to_route(controller), '*' + ROUTE_SUFFIX)].map do |f|
|
31
|
+
File.basename(f, File.extname(f))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def controller_exists? name
|
36
|
+
path = dst_path(:controllers, class_to_route(name))
|
37
|
+
File.file?(path + CONTROLLER_SUFFIX) && path
|
38
|
+
end
|
39
|
+
|
40
|
+
def model_exists? name
|
41
|
+
path = dst_path(:models, class_to_route(name))
|
42
|
+
File.file?(path + MODEL_SUFFIX) && path
|
43
|
+
end
|
44
|
+
|
45
|
+
def app_models
|
46
|
+
load_boot_rb
|
47
|
+
identity_methods = ORM_IDENTITY_METHODS[Cfg[:orm].to_s.to_sym]
|
48
|
+
return [] unless identity_methods
|
49
|
+
ObjectSpace.each_object(Class).select do |o|
|
50
|
+
identity_methods.all? {|m| o.respond_to?(m)} && model_exists?(o.name)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def migrations_by_model model
|
55
|
+
Dir[dst_path(:migrations, class_to_route(model), '*' + MIGRATION_SUFFIX)].map do |f|
|
56
|
+
File.basename(f)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def view_setups_for ctrl, action
|
61
|
+
boot_app
|
62
|
+
ctrl_instance = ctrl.new
|
63
|
+
ctrl_instance.respond_to?(action.to_sym) || fail('"%s" route does not exists' % action)
|
64
|
+
|
65
|
+
action_name, request_method = deRESTify_action(action)
|
66
|
+
ctrl_instance.action_setup = ctrl.action_setup[action_name][request_method]
|
67
|
+
ctrl_instance.call_setups!
|
68
|
+
[
|
69
|
+
File.join(ctrl_instance.view_path?, ctrl_instance.view_prefix?),
|
70
|
+
ctrl_instance.engine_ext?
|
71
|
+
]
|
72
|
+
end
|
73
|
+
|
74
|
+
def app_config
|
75
|
+
pv, $VERBOSE = $VERBOSE, nil
|
76
|
+
load dst_path.config_rb
|
77
|
+
Cfg
|
78
|
+
ensure
|
79
|
+
$VERBOSE = pv
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Enginery
|
2
|
+
class Failure
|
3
|
+
attr_reader :failures
|
4
|
+
def initialize *failures
|
5
|
+
@failures = failures
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module Helpers
|
10
|
+
include EUtils
|
11
|
+
|
12
|
+
def src_path *args
|
13
|
+
@src_path_map ||= begin
|
14
|
+
paths = { :root => File.expand_path('../../../../app', __FILE__) + '/' }
|
15
|
+
[
|
16
|
+
:base,
|
17
|
+
:gemfiles,
|
18
|
+
:rakefiles,
|
19
|
+
:specfiles,
|
20
|
+
:database,
|
21
|
+
:migrations,
|
22
|
+
:layouts,
|
23
|
+
].each {|d| paths[d] = File.join(paths[:root], d.to_s, '')}
|
24
|
+
paths.values.map(&:freeze)
|
25
|
+
[paths, Struct.new(*paths.keys).new(*paths.values)]
|
26
|
+
end
|
27
|
+
paths, struct = @src_path_map
|
28
|
+
return struct if args.empty?
|
29
|
+
|
30
|
+
paths[args.first] || fail('%s is not a recognized source path.
|
31
|
+
Use one of %s' % [args.first.inspect, paths.map(&:inspect)*', '])
|
32
|
+
File.join(paths[args.shift], *args.map(&:to_s)).gsub(/\/+/, '/').freeze
|
33
|
+
end
|
34
|
+
|
35
|
+
def dst_path *args
|
36
|
+
@dst_path_map ||= begin
|
37
|
+
paths = { :root => @dst_root.to_s.gsub(/\/+/, '/') }
|
38
|
+
[
|
39
|
+
:base,
|
40
|
+
:config,
|
41
|
+
].each {|p| paths[p] = File.join(paths[:root], p.to_s, '')}
|
42
|
+
[
|
43
|
+
:controllers,
|
44
|
+
:models,
|
45
|
+
:views,
|
46
|
+
:specs,
|
47
|
+
:migrations,
|
48
|
+
:helpers
|
49
|
+
].each {|d| paths[d] = File.join(paths[:base], d.to_s, '')}
|
50
|
+
|
51
|
+
paths[:rear_controllers] = File.join(paths[:controllers], 'rear-controllers', '')
|
52
|
+
paths[:config_rb] = File.join(paths[:base], 'config.rb')
|
53
|
+
paths[:config_yml] = File.join(paths[:config], 'config.yml')
|
54
|
+
paths[:database_yml] = File.join(paths[:config], 'database.yml')
|
55
|
+
|
56
|
+
[
|
57
|
+
:Rakefile,
|
58
|
+
:Gemfile,
|
59
|
+
].each {|f| paths[f] = File.join(paths[:root], f.to_s)}
|
60
|
+
[
|
61
|
+
:boot_rb,
|
62
|
+
:database_rb,
|
63
|
+
].each {|f| paths[f] = File.join(paths[:base], f.to_s.sub('_rb', '.rb'))}
|
64
|
+
paths.values.map(&:freeze)
|
65
|
+
[paths, Struct.new(*paths.keys).new(*paths.values)]
|
66
|
+
end
|
67
|
+
paths, struct = @dst_path_map
|
68
|
+
return struct if args.empty?
|
69
|
+
|
70
|
+
paths[args.first] || fail('%s is not a recognized destination path.
|
71
|
+
Use one of %s' % [args.first.inspect, paths.map(&:inspect)*', '])
|
72
|
+
File.join(paths[args.shift], *args.map(&:to_s)).gsub(/\/+/, '/').freeze
|
73
|
+
end
|
74
|
+
|
75
|
+
def unrootify path, root = nil
|
76
|
+
root = (root || dst_path.root).gsub(/\/+/, '/')
|
77
|
+
regexp = /\A#{Regexp.escape(root)}\/?/
|
78
|
+
path.gsub(/\/+/, '/').sub(regexp, '')
|
79
|
+
end
|
80
|
+
|
81
|
+
def o *chunks
|
82
|
+
@logger ||= Logger.new(STDOUT)
|
83
|
+
opts = chunks.last.is_a?(Hash) ? chunks.pop : {}
|
84
|
+
@logger << "%s\n" % chunks.join(opts[:join].to_s)
|
85
|
+
end
|
86
|
+
module_function :o
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def write_file file, data
|
91
|
+
o '*** Writing "%s" ***' % unrootify(file).gsub('::', '_')
|
92
|
+
File.open(file, 'w') {|f| f << (data.respond_to?(:join) ? data.join : data)}
|
93
|
+
end
|
94
|
+
|
95
|
+
def update_file file, data
|
96
|
+
o '*** Updating "%s" ***' % unrootify(file)
|
97
|
+
File.open(file, 'a+') {|f| f << (data.respond_to?(:join) ? data.join : data)}
|
98
|
+
end
|
99
|
+
|
100
|
+
def namespace_to_source_code name
|
101
|
+
names, constants = name.split('::'), []
|
102
|
+
|
103
|
+
names.uniq.size == names.size ||
|
104
|
+
fail('%s namespace constants duplicates' % name)
|
105
|
+
|
106
|
+
names.map(&:to_sym).inject(Object) do |ns,c|
|
107
|
+
validate_constant_name(c)
|
108
|
+
c_class, next_ns = Module, nil
|
109
|
+
|
110
|
+
if ns && ns.const_defined?(c)
|
111
|
+
next_ns = ns.const_get(c)
|
112
|
+
c_class = next_ns.class
|
113
|
+
[Class, Module].include?(c_class) ||
|
114
|
+
fail('%s should be a Class or a Module. It is a %s instead' % [constants.keys*'::', c_class])
|
115
|
+
end
|
116
|
+
|
117
|
+
constants << [c, c_class.name.downcase]
|
118
|
+
next_ns
|
119
|
+
end
|
120
|
+
|
121
|
+
constant_name = constants.pop.first.to_s
|
122
|
+
|
123
|
+
before, after = [], []
|
124
|
+
constants.each do |(cn,cc)|
|
125
|
+
i = INDENT * before.size
|
126
|
+
before << '%s%s %s' % [i, cc, cn]
|
127
|
+
after << '%send' % i
|
128
|
+
end
|
129
|
+
[before, constant_name, after.reverse << '']
|
130
|
+
end
|
131
|
+
|
132
|
+
def constant_defined? name
|
133
|
+
return unless name
|
134
|
+
namespace = name.to_s.strip.sub(/\A::/, '').split('::').map {|c| validate_constant_name c}
|
135
|
+
namespace.inject(Object) do |o,c|
|
136
|
+
o.const_defined?(c.to_sym) ? o.const_get(c) : break
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def output_source_code source
|
141
|
+
(source.is_a?(String) ? File.readlines(source) : source).each {|l| o "+ " + l.chomp}
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module Enginery
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
# TODO: refactor this huge method
|
5
|
+
def parse_input *input
|
6
|
+
input.flatten!
|
7
|
+
args, setups, string_setups = [], {}, []
|
8
|
+
input.each do |a|
|
9
|
+
case
|
10
|
+
|
11
|
+
# generator
|
12
|
+
when a =~ /\Ao(rm)?:/
|
13
|
+
orm = extract_setup(a)
|
14
|
+
if valid_orm = valid_orm?(orm)
|
15
|
+
setups[:orm] = valid_orm
|
16
|
+
string_setups << a
|
17
|
+
else
|
18
|
+
fail_verbosely 'Invalid ORM provided - "%s"' % orm, \
|
19
|
+
'Supported ORMs: ActiveRecord, DataMapper, Sequel'
|
20
|
+
end
|
21
|
+
when a =~ /\Ae(ngine)?:/
|
22
|
+
smth = extract_setup(a)
|
23
|
+
if engine = valid_engine?(smth)
|
24
|
+
setups[:engine] = engine
|
25
|
+
string_setups << a
|
26
|
+
else
|
27
|
+
fail_verbosely 'Invalid engine provided - %s' % smth, \
|
28
|
+
'Supported engines(Case Sensitive): %s' % EConstants::VIEW__ENGINE_BY_SYM.keys.join(', ')
|
29
|
+
end
|
30
|
+
when a =~ /\Af(ormat|ile)?:/
|
31
|
+
if format = extract_setup(a)
|
32
|
+
# format if used by generator, file is used by migrator
|
33
|
+
setups[:format] = setups[:file] = format
|
34
|
+
string_setups << a
|
35
|
+
end
|
36
|
+
when a =~ /\Ar(oute)?:/
|
37
|
+
if route = extract_setup(a)
|
38
|
+
setups[:route] = route
|
39
|
+
string_setups << a
|
40
|
+
end
|
41
|
+
when a =~ /\Adb/
|
42
|
+
[:type, :host, :port, :name, :user, :pass].each do |s|
|
43
|
+
if (a =~ /\Adb(_)?#{s}:/) && (v = extract_setup(a))
|
44
|
+
(setups[:db] ||= {}).update s => (s == :type ? valid_db_type?(v) : v)
|
45
|
+
string_setups << a
|
46
|
+
end
|
47
|
+
end
|
48
|
+
when a =~ /\As(erver)?:/
|
49
|
+
smth = extract_setup(a)
|
50
|
+
if server = valid_server?(smth)
|
51
|
+
setups[:server] = server.to_sym
|
52
|
+
string_setups << a
|
53
|
+
else
|
54
|
+
fail_verbosely 'Unknown server provided - %s' % smth, \
|
55
|
+
'It wont be added to Gemfile nor to config.yml', \
|
56
|
+
'Known servers(Case Sensitive): %s' % KNOWN_WEB_SERVERS.join(', ')
|
57
|
+
end
|
58
|
+
when a =~ /\Ap(ort)?:/
|
59
|
+
smth = extract_setup(a)
|
60
|
+
if (port = smth.to_i) > 0
|
61
|
+
setups[:port] = port
|
62
|
+
string_setups << a
|
63
|
+
else
|
64
|
+
fail_verbosely 'Invalid port provided - %s' % smth, 'Port should be a number'
|
65
|
+
end
|
66
|
+
when a =~ /\Ah(ost(s)?)?:/
|
67
|
+
if hosts = extract_setup(a)
|
68
|
+
setups[:hosts] = hosts.split(',')
|
69
|
+
string_setups << a
|
70
|
+
end
|
71
|
+
when a =~ /\Ai(nclude)?:/
|
72
|
+
mdl = validate_constant_name extract_setup(a)
|
73
|
+
(setups[:include] ||= []).push mdl
|
74
|
+
string_setups << a
|
75
|
+
|
76
|
+
# migrator
|
77
|
+
when a =~ /\Acreate_table_for:/
|
78
|
+
if table = extract_setup(a)
|
79
|
+
setups[:create_table] = table
|
80
|
+
string_setups << a
|
81
|
+
end
|
82
|
+
when a =~ /\Am(odel)?:/
|
83
|
+
if table = extract_setup(a)
|
84
|
+
setups[:update_table] = table
|
85
|
+
string_setups << a
|
86
|
+
end
|
87
|
+
when a =~ /\Aa?(dd_)?c(olumn)?:/
|
88
|
+
if column = extract_setup(a)
|
89
|
+
(setups[:create_columns] ||= []).push column.split(':')
|
90
|
+
string_setups << a
|
91
|
+
end
|
92
|
+
when a =~ /\Au(pdate_)?c?(olumn)?:/
|
93
|
+
if column = extract_setup(a)
|
94
|
+
(setups[:update_columns] ||= []).push column.split(':')
|
95
|
+
string_setups << a
|
96
|
+
end
|
97
|
+
when a =~ /\Ar(ename_)?c?(olumn)?:/
|
98
|
+
if column = extract_setup(a)
|
99
|
+
(setups[:rename_columns] ||= []).push column.split(':')
|
100
|
+
string_setups << a
|
101
|
+
end
|
102
|
+
else
|
103
|
+
args.push(a) unless ORM_ASSOCIATIONS.find {|an| a =~ /#{an}/}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
ORM_ASSOCIATIONS.each do |a|
|
107
|
+
input.select {|x| x =~ /\A#{a}:/}.each do |s|
|
108
|
+
next unless v = extract_setup(s)
|
109
|
+
(setups[a] ||= []).push v
|
110
|
+
string_setups << s
|
111
|
+
end
|
112
|
+
end
|
113
|
+
[args.freeze, setups.freeze, string_setups.join(' ').freeze]
|
114
|
+
end
|
115
|
+
module_function :parse_input
|
116
|
+
|
117
|
+
def extract_setup input
|
118
|
+
input.scan(/:(.+)/).flatten.last
|
119
|
+
end
|
120
|
+
module_function :extract_setup
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Enginery
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def activerecord_associations setups = {}
|
5
|
+
ORM_ASSOCIATIONS.inject([]) do |lines,a|
|
6
|
+
(setups[a]||[]).each do |s|
|
7
|
+
line, input = nil, s.split(':')
|
8
|
+
target = input[0]
|
9
|
+
if target =~ /\W/
|
10
|
+
o '*** WARN: invalid association target "%s", association not added ***' % target
|
11
|
+
else
|
12
|
+
line = '%s :%s' % [a, target]
|
13
|
+
if through = input[1].to_s =~ /through/ && input[2]
|
14
|
+
if through =~ /\W/
|
15
|
+
o '*** WARN: invalid :through option "%s", association not added ***' % through
|
16
|
+
line = nil
|
17
|
+
else
|
18
|
+
line << ', through: :%s' % through
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
lines.push(line) if line
|
23
|
+
end
|
24
|
+
lines
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def datamapper_associations setups = {}
|
29
|
+
ORM_ASSOCIATIONS.inject([]) do |lines,a|
|
30
|
+
(setups[a]||[]).each do |s|
|
31
|
+
line, input = nil, s.split(':')
|
32
|
+
target = input[0]
|
33
|
+
if target =~ /\W/
|
34
|
+
o '*** WARN: invalid association target "%s", association not added ***' % target
|
35
|
+
else
|
36
|
+
if a == :has_one
|
37
|
+
line = 'has 1, :%s' % target
|
38
|
+
elsif a =~ /has_(and|many)/
|
39
|
+
line = 'has n, :%s' % target
|
40
|
+
else
|
41
|
+
line = '%s :%s' % [a, target]
|
42
|
+
end
|
43
|
+
if through = input[1].to_s =~ /through/ && input[2]
|
44
|
+
if through =~ /\W/
|
45
|
+
o '*** WARN: invalid :through option "%s", association not added ***' % through
|
46
|
+
line = nil
|
47
|
+
else
|
48
|
+
line << ', through: :%s' % through
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
lines.push(line) if line
|
53
|
+
end
|
54
|
+
lines
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def sequel_associations setups = {}
|
59
|
+
ORM_ASSOCIATIONS.inject([]) do |lines,a|
|
60
|
+
(setups[a]||[]).each do |s|
|
61
|
+
line, input = nil, s.split(':')
|
62
|
+
target = input[0]
|
63
|
+
if target =~ /\W/
|
64
|
+
o '*** WARN: invalid association target "%s", association not added ***' % target
|
65
|
+
else
|
66
|
+
case a
|
67
|
+
when :belongs_to
|
68
|
+
line = 'many_to_one :%s' % target
|
69
|
+
when :has_one
|
70
|
+
line = 'one_to_one :%s' % target
|
71
|
+
when :has_many
|
72
|
+
line = 'one_to_many :%s' % target
|
73
|
+
when :has_and_belongs_to_many
|
74
|
+
line = 'many_to_many :%s' % target
|
75
|
+
end
|
76
|
+
if through = input[1].to_s =~ /through/ && input[2]
|
77
|
+
o '*** INFO: Sequel does not support :through option, ignoring ***' % through
|
78
|
+
end
|
79
|
+
end
|
80
|
+
lines.push(line) if line
|
81
|
+
end
|
82
|
+
lines
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
module Enginery
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
def in_app_folder?
|
5
|
+
File.directory?(dst_path.controllers)
|
6
|
+
end
|
7
|
+
|
8
|
+
def fail_unless_in_app_folder!
|
9
|
+
in_app_folder? || fail("Seems current folder does not contain a Espresso application")
|
10
|
+
end
|
11
|
+
|
12
|
+
def fail *failures
|
13
|
+
throw :enginery_failures, Failure.new(*failures)
|
14
|
+
end
|
15
|
+
module_function :fail
|
16
|
+
|
17
|
+
def fail_verbosely *failures
|
18
|
+
o *failures
|
19
|
+
fail *failures
|
20
|
+
end
|
21
|
+
module_function :fail_verbosely
|
22
|
+
|
23
|
+
def valid_server? smth
|
24
|
+
server = smth.to_s.to_sym
|
25
|
+
KNOWN_WEB_SERVERS.include?(server) ? server : false
|
26
|
+
end
|
27
|
+
module_function :valid_server?
|
28
|
+
|
29
|
+
def valid_orm? smth
|
30
|
+
return unless smth.is_a?(String) || smth.is_a?(Symbol)
|
31
|
+
case
|
32
|
+
when smth =~ /\Aa/i
|
33
|
+
:ActiveRecord
|
34
|
+
when smth =~ /\Ad/i
|
35
|
+
:DataMapper
|
36
|
+
when smth =~ /\As/i
|
37
|
+
:Sequel
|
38
|
+
end
|
39
|
+
end
|
40
|
+
module_function :valid_orm?
|
41
|
+
|
42
|
+
def valid_db_type? smth
|
43
|
+
return unless smth.is_a?(String) || smth.is_a?(Symbol)
|
44
|
+
case
|
45
|
+
when smth =~ /\Am/i
|
46
|
+
:mysql
|
47
|
+
when smth =~ /\Ap/i
|
48
|
+
:postgres
|
49
|
+
when smth =~ /\As/i
|
50
|
+
:sqlite
|
51
|
+
end
|
52
|
+
end
|
53
|
+
module_function :valid_db_type?
|
54
|
+
|
55
|
+
def valid_engine? smth
|
56
|
+
engine = smth.to_s.to_sym
|
57
|
+
EConstants::VIEW__ENGINE_BY_SYM.has_key?(engine) ? engine : false
|
58
|
+
end
|
59
|
+
module_function :valid_engine?
|
60
|
+
|
61
|
+
def valid_controller? name
|
62
|
+
name.nil? || name.empty? && fail("Please provide controller name")
|
63
|
+
ctrl_path = controller_exists?(name) || fail('"%s" controller does not exists' % name)
|
64
|
+
|
65
|
+
ctrl = name.split('::').map(&:to_sym).inject(Object) do |ns,c|
|
66
|
+
ctrl_dirname = unrootify(ctrl_path)
|
67
|
+
ns.const_defined?(c) || fail("#{ctrl_dirname} exists but #{name} controller not defined.
|
68
|
+
Please define it manually or delete #{ctrl_dirname} and start over.")
|
69
|
+
ns.const_get(c)
|
70
|
+
end
|
71
|
+
[ctrl_path, ctrl]
|
72
|
+
end
|
73
|
+
|
74
|
+
def valid_route? ctrl_name, name
|
75
|
+
ctrl_path, ctrl = valid_controller?(ctrl_name)
|
76
|
+
name.nil? || name.empty? && fail("Please provide route name")
|
77
|
+
path_rules = ctrl.path_rules.inject({}) do |map,(r,s)|
|
78
|
+
map.merge %r[#{Regexp.escape s}] => r.source
|
79
|
+
end
|
80
|
+
route = action_to_route(name, path_rules)
|
81
|
+
validate_route_name(route)
|
82
|
+
file = File.join(ctrl_path, route + '.rb')
|
83
|
+
[file, route]
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_constant_name constant
|
87
|
+
constant =~ /[^\w|\d|\:]/ && fail("Wrong constant name - %s, it should contain only alphanumerics" % constant)
|
88
|
+
constant =~ /\A[0-9]/ && fail("Wrong constant name - %s, it should start with a letter" % constant)
|
89
|
+
constant =~ /\A[A-Z]/ || fail("Wrong constant name - %s, it should start with a uppercase letter" % constant)
|
90
|
+
constant
|
91
|
+
end
|
92
|
+
module_function :validate_constant_name
|
93
|
+
|
94
|
+
def validate_route_name name
|
95
|
+
name =~ /\W/ && fail("Routes may contain only alphanumerics")
|
96
|
+
name
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|