my_enginery 0.2.8
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.
- 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
|