tanuki 0.3.0 → 0.3.1
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/LICENSE +1 -1
- data/README.rdoc +10 -2
- data/app/tanuki/attribute/attribute.rb +2 -2
- data/app/tanuki/base/base.rb +2 -2
- data/app/tanuki/controller/controller.rb +2 -2
- data/app/tanuki/controller/default.thtml +1 -1
- data/app/tanuki/controller/index.thtml +1 -1
- data/app/tanuki/controller/link.thtml +1 -1
- data/app/tanuki/manager/controller/controller.rb +2 -0
- data/app/tanuki/manager/page/page.rb +2 -0
- data/app/tanuki/meta_model/manager.ttxt +1 -1
- data/app/tanuki/meta_model/manager_base.ttxt +2 -2
- data/app/tanuki/meta_model/meta_model.rb +2 -2
- data/app/tanuki/meta_model/model.ttxt +1 -1
- data/app/tanuki/meta_model/model_base.ttxt +2 -2
- data/app/tanuki/model/controller/controller.rb +2 -0
- data/app/tanuki/model/model.rb +2 -2
- data/app/tanuki/model/page/page.rb +2 -0
- data/app/tanuki/page/missing/default.thtml +1 -1
- data/app/tanuki/page/missing/missing.rb +2 -2
- data/app/user/page/index/default.thtml +1 -1
- data/app/user/page/index/index.rb +2 -2
- data/bin/tanuki +3 -201
- data/config/common.rb +1 -1
- data/config/common_application.rb +3 -3
- data/config/development_application.rb +1 -1
- data/config/production_application.rb +1 -1
- data/config/test_application.rb +2 -0
- data/lib/tanuki/application.rb +27 -7
- data/lib/tanuki/argument/base.rb +3 -3
- data/lib/tanuki/argument/integer.rb +3 -3
- data/lib/tanuki/argument/integer_range.rb +3 -3
- data/lib/tanuki/argument/string.rb +3 -3
- data/lib/tanuki/argument.rb +3 -3
- data/lib/tanuki/behavior/controller_behavior.rb +40 -8
- data/lib/tanuki/behavior/meta_model_behavior.rb +62 -20
- data/lib/tanuki/behavior/model_behavior.rb +4 -4
- data/lib/tanuki/behavior/object_behavior.rb +2 -2
- data/lib/tanuki/configurator.rb +2 -2
- data/lib/tanuki/context.rb +8 -3
- data/lib/tanuki/extensions/module.rb +16 -1
- data/lib/tanuki/extensions/rack/builder.rb +2 -2
- data/lib/tanuki/extensions/rack/server.rb +2 -2
- data/lib/tanuki/extensions/rack/static_dir.rb +2 -2
- data/lib/tanuki/i18n.rb +2 -2
- data/lib/tanuki/launcher.rb +2 -2
- data/lib/tanuki/loader.rb +24 -4
- data/lib/tanuki/model_generator.rb +114 -0
- data/lib/tanuki/template_compiler.rb +89 -13
- data/lib/tanuki/utility/create.rb +38 -0
- data/lib/tanuki/utility/generate.rb +52 -0
- data/lib/tanuki/utility/help.rb +16 -0
- data/lib/tanuki/utility/server.rb +23 -0
- data/lib/tanuki/utility/version.rb +15 -0
- data/lib/tanuki/utility.rb +65 -0
- data/lib/tanuki/version.rb +2 -2
- data/lib/tanuki.rb +1 -2
- data/schema/tanuki/l10n/en/controller.yml +1 -1
- data/schema/tanuki/l10n/en/page.yml +1 -1
- data/schema/tanuki/l10n/ru/controller.yml +1 -1
- data/schema/tanuki/l10n/ru/page.yml +1 -1
- data/schema/tanuki/models/controller.yml +1 -1
- data/schema/tanuki/models/page.yml +1 -1
- metadata +16 -5
- data/lib/tanuki/extensions/object.rb +0 -12
data/LICENSE
CHANGED
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
16
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
17
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
18
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
-
THE SOFTWARE.
|
19
|
+
THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -17,6 +17,14 @@ Fire up the terminal and type:
|
|
17
17
|
|
18
18
|
View the result at: http://localhost:3000
|
19
19
|
|
20
|
-
==
|
20
|
+
== Hack on the Core
|
21
21
|
|
22
|
-
{
|
22
|
+
If you would like to study the framework and contribute, try making sense of the project {wiki}[https://github.com/assistunion/tanuki/wiki], then move on to {documentation}[http://rubydoc.info/github/assistunion/tanuki].
|
23
|
+
|
24
|
+
== Acknowledgements
|
25
|
+
|
26
|
+
Tanuki is thankful to:
|
27
|
+
|
28
|
+
* All of the core contributors
|
29
|
+
* Erika Olehno, for the cute logo
|
30
|
+
* {Rack}[http://rack.rubyforge.org/], {Sequel}[http://sequel.rubyforge.org/], {escape_utils}[https://github.com/brianmario/escape_utils], and {Active Support}[https://github.com/rails/rails/tree/master/activesupport] authors and contributors, for their amazing work
|
data/app/tanuki/base/base.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
class
|
1
|
+
class Tanuki::Base
|
2
2
|
include Tanuki::BaseBehavior
|
3
|
-
end
|
3
|
+
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
class
|
1
|
+
class Tanuki::Controller < Tanuki::Base
|
2
2
|
include Tanuki::ControllerBehavior
|
3
|
-
end
|
3
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
<%= self.class %> is under construction
|
1
|
+
<%= self.class %> is under construction
|
@@ -1,2 +1,2 @@
|
|
1
1
|
class <%= class_name_for :manager %>
|
2
|
-
end
|
2
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
class <%= class_name_for :manager_base %> <
|
2
|
-
end
|
1
|
+
class <%= class_name_for :manager_base %> < Tanuki::Controller
|
2
|
+
end
|
@@ -1,3 +1,3 @@
|
|
1
|
-
class
|
1
|
+
class Tanuki::MetaModel < Tanuki::Base
|
2
2
|
include Tanuki::MetaModelBehavior
|
3
|
-
end
|
3
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
1
|
class <%= class_name_for :model %>
|
2
|
-
end
|
2
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class <%= class_name_for :model_base %> <
|
1
|
+
class <%= class_name_for :model_base %> < Tanuki::Base
|
2
2
|
extend Tanuki::ModelBehavior
|
3
3
|
|
4
4
|
class << self
|
@@ -9,4 +9,4 @@ class <%= class_name_for :model_base %> < Tanuki_Base
|
|
9
9
|
def get(ctx, *args)
|
10
10
|
end
|
11
11
|
end
|
12
|
-
end
|
12
|
+
end
|
data/app/tanuki/model/model.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
class
|
1
|
+
class Tanuki::Model
|
2
2
|
include Tanuki::ModelBehavior
|
3
|
-
end
|
3
|
+
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
class
|
2
|
-
end
|
1
|
+
class User::Page::Index < Tanuki::Controller
|
2
|
+
end
|
data/bin/tanuki
CHANGED
@@ -1,202 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
class << self
|
7
|
-
|
8
|
-
def create(name)
|
9
|
-
unless name
|
10
|
-
puts "To use this command: `create <name>'"
|
11
|
-
return
|
12
|
-
end
|
13
|
-
require 'fileutils'
|
14
|
-
project_dir = File.expand_path(name)
|
15
|
-
if File.exists? project_dir
|
16
|
-
puts "File or directory `#{name}' already exists!"
|
17
|
-
return
|
18
|
-
end
|
19
|
-
version unless @in_repl
|
20
|
-
puts "\n creating #{name = name.downcase}"
|
21
|
-
FileUtils.mkdir project_dir
|
22
|
-
file_source = File.expand_path(File.join('..', '..'), __FILE__)
|
23
|
-
puts " creating #{File.join(name, 'app')}"
|
24
|
-
FileUtils.mkdir_p File.join(project_dir, 'app', 'user')
|
25
|
-
FileUtils.cp_r File.join(file_source, 'app', 'user'), File.join(project_dir, 'app')
|
26
|
-
puts " creating #{File.join(name, 'gen')}"
|
27
|
-
FileUtils.mkdir(gen_dir = File.join(project_dir, 'gen'))
|
28
|
-
FileUtils.chmod(0777, gen_dir)
|
29
|
-
puts " creating #{File.join(name, 'public')}"
|
30
|
-
FileUtils.mkdir(File.join(project_dir, 'public'))
|
31
|
-
puts " creating #{File.join(name, 'schema')}"
|
32
|
-
FileUtils.mkdir(File.join(project_dir, 'schema'))
|
33
|
-
Dir.chdir(project_dir) if @in_repl
|
34
|
-
end
|
35
|
-
|
36
|
-
def generate(cwd)
|
37
|
-
version unless @in_repl
|
38
|
-
cwd = cwd ? File.expand_path(cwd) : Dir.pwd
|
39
|
-
puts "Working directory is: #{cwd}\nTo specify another: `generate <path>'"
|
40
|
-
require 'active_support/inflector'
|
41
|
-
require 'yaml'
|
42
|
-
require 'fileutils'
|
43
|
-
require 'tanuki/extensions/object'
|
44
|
-
require 'tanuki/behavior/meta_model_behavior'
|
45
|
-
require 'tanuki/behavior/model_behavior'
|
46
|
-
require 'tanuki/behavior/object_behavior'
|
47
|
-
require 'tanuki/configurator'
|
48
|
-
require 'tanuki/context'
|
49
|
-
require 'tanuki/loader'
|
50
|
-
require 'tanuki/template_compiler'
|
51
|
-
Loader.context = ctx = Context
|
52
|
-
default_root = File.expand_path(File.join('..', '..'), __FILE__)
|
53
|
-
cfg = Configurator.new(Context, cwd)
|
54
|
-
if cwd != default_root
|
55
|
-
cfg.config_root = File.join(default_root, 'config')
|
56
|
-
cfg.load_config :common
|
57
|
-
end
|
58
|
-
cfg.config_root = File.join(cwd, 'config')
|
59
|
-
cfg.load_config :common, cwd != default_root
|
60
|
-
puts "\n looking for models"
|
61
|
-
@tried = {}
|
62
|
-
@models = {}
|
63
|
-
local_schema_root = File.expand_path(File.join('..', '..', 'schema'), __FILE__)
|
64
|
-
generate_in(ctx.schema_root, ctx)
|
65
|
-
generate_in(local_schema_root, ctx) if ctx.schema_root != local_schema_root
|
66
|
-
@tried.each_pair do |name, arys|
|
67
|
-
puts "\n found: #{name}"
|
68
|
-
arys.each_pair {|ary_name, ary| puts %{ #{ary_name}:\n - #{ary.join "\n - "}} unless ary.empty? }
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def generate_in(schema_root, ctx)
|
73
|
-
Dir.entries(schema_root)[2..-1].each do |namespace_path|
|
74
|
-
namespace_name = namespace_path.split('_').map {|s| s.capitalize }.join
|
75
|
-
namespace = @models[namespace_name] = {}
|
76
|
-
Dir.glob(File.join(schema_root, namespace_path, 'models', '*.yml')) do |file_path|
|
77
|
-
model_name = File.basename(file_path, '.yml').split('_').map {|s| s.capitalize }.join
|
78
|
-
meta_model = namespace[model_name] = Tanuki_MetaModel.new(
|
79
|
-
namespace_name,
|
80
|
-
model_name,
|
81
|
-
YAML.load_file(file_path),
|
82
|
-
@models
|
83
|
-
)
|
84
|
-
meta_model.process!
|
85
|
-
if @tried.include? namespace_model_name = "#{namespace_name}.#{model_name}"
|
86
|
-
next
|
87
|
-
else
|
88
|
-
@tried[namespace_model_name] = {:generated => [], :failed => [], :skipped => []}
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
@models.each do |namespace_name, namespace |
|
94
|
-
namespace.each do |model_name, meta_model|
|
95
|
-
meta_model.process_relations!
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
@models.each do |namespace_name, namespace |
|
100
|
-
namespace.each do |model_name, meta_model|
|
101
|
-
namespace_model_name = "#{namespace_name}.#{model_name}"
|
102
|
-
{
|
103
|
-
:model => false,
|
104
|
-
:model_base => true,
|
105
|
-
:manager => false,
|
106
|
-
:manager_base => true
|
107
|
-
}.each do |class_type, base|
|
108
|
-
class_name = meta_model.class_name_for class_type
|
109
|
-
path = Tanuki::Loader.class_path(class_name, base ? ctx.gen_root : ctx.app_root)
|
110
|
-
if base || !(File.exists? path)
|
111
|
-
begin
|
112
|
-
dirname = File.dirname(path)
|
113
|
-
FileUtils.mkdir_p dirname unless File.directory? dirname
|
114
|
-
File.open path, 'w' do |file|
|
115
|
-
writer = proc {|out| file.print out.to_s }
|
116
|
-
Loader.run_template({}, meta_model, class_type).call(writer, ctx)
|
117
|
-
end
|
118
|
-
@tried[namespace_model_name][:generated] << class_name unless base
|
119
|
-
rescue
|
120
|
-
@tried[namespace_model_name][:failed] << class_name unless base
|
121
|
-
end
|
122
|
-
else
|
123
|
-
@tried[namespace_model_name][:skipped] << class_name unless base
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def execute(args)
|
131
|
-
case args[0]
|
132
|
-
when 'create' then create(args[1])
|
133
|
-
when 'exit' then @in_repl ? (puts 'Bye bye!'; return false) : help
|
134
|
-
when 'generate' then generate(args[1])
|
135
|
-
when 'help' then help
|
136
|
-
when 'server' then return server(args[1])
|
137
|
-
when 'version' then version
|
138
|
-
when nil then start_repl unless @in_repl
|
139
|
-
else help
|
140
|
-
end
|
141
|
-
true
|
142
|
-
end
|
143
|
-
|
144
|
-
def help
|
145
|
-
version unless @in_repl
|
146
|
-
puts "\nbasic commands:\n"
|
147
|
-
commands = {}
|
148
|
-
commands['create'] = 'create a new app with the given name'
|
149
|
-
commands['exit'] = 'exit this utility' if @in_repl
|
150
|
-
commands['generate'] = 'generate models for application schema'
|
151
|
-
commands['help'] = 'show help (this text)'
|
152
|
-
commands['server'] = 'run application'
|
153
|
-
commands['version'] = 'show framework version'
|
154
|
-
commands.each_pair {|k, v| puts ' %-8s %s' % [k, v] }
|
155
|
-
end
|
156
|
-
|
157
|
-
def init
|
158
|
-
@in_repl = false
|
159
|
-
execute ARGV
|
160
|
-
end
|
161
|
-
|
162
|
-
def server(env=nil)
|
163
|
-
env = env ? env.to_sym : :development
|
164
|
-
puts %{Calling for a Tanuki in "#{Dir.pwd}"}
|
165
|
-
version unless @in_repl
|
166
|
-
require 'tanuki'
|
167
|
-
begin
|
168
|
-
Application.run
|
169
|
-
false
|
170
|
-
rescue Interrupt
|
171
|
-
puts 'Tanuki ran away!'
|
172
|
-
false
|
173
|
-
rescue SystemCallError
|
174
|
-
puts 'Tanuki ran away! Someone else is playing here.'
|
175
|
-
true
|
176
|
-
end if Application.configure(env)
|
177
|
-
end
|
178
|
-
|
179
|
-
def start_repl
|
180
|
-
@in_repl = true
|
181
|
-
version
|
182
|
-
print 'tanuki>'
|
183
|
-
print "\ntanuki>" while gets && execute($_.chomp.scan /(?<=")\w[\w\s]*(?=")|\w+/)
|
184
|
-
end
|
185
|
-
|
186
|
-
def version
|
187
|
-
begin
|
188
|
-
require 'tanuki/version'
|
189
|
-
rescue LoadError
|
190
|
-
$:.unshift File.expand_path(File.join('..', '..', 'lib'), __FILE__)
|
191
|
-
require 'tanuki/version'
|
192
|
-
end
|
193
|
-
puts "Tanuki version #{VERSION}"
|
194
|
-
end
|
195
|
-
|
196
|
-
end # end class << self
|
197
|
-
|
198
|
-
end # end Utility
|
199
|
-
|
200
|
-
end # end Tanuki
|
201
|
-
|
202
|
-
Tanuki::Utility.init if File.basename(__FILE__) == File.basename($0)
|
2
|
+
$:.unshift File.expand_path(File.join('..', '..', 'lib'), __FILE__)
|
3
|
+
require 'tanuki/utility'
|
4
|
+
Tanuki::Utility.init if File.basename(__FILE__) == File.basename($0)
|
data/config/common.rb
CHANGED
@@ -11,8 +11,8 @@ set :port, 3000
|
|
11
11
|
set :development, false
|
12
12
|
|
13
13
|
# Default controllers
|
14
|
-
set :root_page, ::
|
15
|
-
set :missing_page, ::
|
14
|
+
set :root_page, ::User::Page::Index
|
15
|
+
set :missing_page, ::Tanuki::Page::Missing
|
16
16
|
|
17
17
|
# Internationalization
|
18
18
|
set :i18n, false
|
@@ -30,4 +30,4 @@ visitor :string do s = ''; proc {|out| s << out.to_s } end
|
|
30
30
|
argument Fixnum, Argument::Integer
|
31
31
|
argument Bignum, Argument::Integer
|
32
32
|
argument Range, Argument::IntegerRange
|
33
|
-
argument String, Argument::String
|
33
|
+
argument String, Argument::String
|
@@ -1,2 +1,2 @@
|
|
1
1
|
load_config :common_application
|
2
|
-
set :development, false
|
2
|
+
set :development, false
|
data/lib/tanuki/application.rb
CHANGED
@@ -17,12 +17,17 @@ module Tanuki
|
|
17
17
|
begin
|
18
18
|
default_root = File.expand_path(File.join('..', '..', '..'), __FILE__)
|
19
19
|
@cfg = Configurator.new(Context, pwd = Dir.pwd)
|
20
|
+
|
21
|
+
# Configure in default root (e.g. gem root)
|
20
22
|
if pwd != default_root
|
21
23
|
@cfg.config_root = File.join(default_root, 'config')
|
22
24
|
@cfg.load_config(([:development, :production].include? env) ? :"#{env}_application" : :common_application)
|
23
25
|
end
|
26
|
+
|
27
|
+
# Configure in application root
|
24
28
|
@cfg.config_root = File.join(pwd, 'config')
|
25
29
|
@cfg.load_config :"#{env}_application", pwd != default_root
|
30
|
+
|
26
31
|
return true
|
27
32
|
rescue NameError => e
|
28
33
|
if e.name =~ /\AA-Z/
|
@@ -54,10 +59,14 @@ module Tanuki
|
|
54
59
|
def run
|
55
60
|
configure_middleware(rack_builder = Rack::Builder.new)
|
56
61
|
rack_builder.run(rack_app)
|
62
|
+
|
63
|
+
# Choose and start a Rack handler
|
57
64
|
@context.running_server = available_server
|
58
|
-
|
59
|
-
|
60
|
-
|
65
|
+
@context.running_server.run rack_builder.to_app, :Host => @context.host, :Port => @context.port do |server|
|
66
|
+
[:INT, :TERM].each {|sig| trap(sig) { (server.respond_to? :stop!) ? server.stop! : server.stop } }
|
67
|
+
puts "A#{'n' if @environment =~ /\A[aeiou]/} #{@environment} Tanuki appears! Press Ctrl-C to set it free.",
|
68
|
+
"You used #{@context.running_server.name.gsub(/.*::/, '')} at #{@context.host}:#{@context.port}."
|
69
|
+
end
|
61
70
|
end
|
62
71
|
|
63
72
|
# Adds a given +middleware+ with optional +args+ and +block+ to the Rack middleware pipeline.
|
@@ -115,14 +124,23 @@ module Tanuki
|
|
115
124
|
proc do |env|
|
116
125
|
request_ctx = ctx.child
|
117
126
|
request_ctx.templates = {}
|
127
|
+
|
128
|
+
# If there are trailing slashes in path, don't dispatch
|
118
129
|
if match = env['PATH_INFO'].match(/^(.+)(?<!\$)\/$/)
|
130
|
+
|
131
|
+
# Remove trailing slash in the path and redirect
|
119
132
|
loc = match[1]
|
120
133
|
loc << "?#{env['QUERY_STRING']}" unless env['QUERY_STRING'].empty?
|
121
134
|
[301, {'Location' => loc, 'Content-Type' => 'text/html; charset=utf-8'}, []]
|
135
|
+
|
122
136
|
else
|
137
|
+
|
138
|
+
# Dispatch controller chain for the current path
|
123
139
|
request_ctx.env = env
|
124
140
|
result = ::Tanuki::ControllerBehavior.dispatch(request_ctx, ctx.i18n ? ::Tanuki::I18n : ctx.root_page,
|
125
141
|
Rack::Utils.unescape(env['PATH_INFO']).force_encoding('UTF-8'))
|
142
|
+
|
143
|
+
# Handle dispatch result
|
126
144
|
case result[:type]
|
127
145
|
when :redirect then
|
128
146
|
[302, {'Location' => result[:location], 'Content-Type' => 'text/html; charset=utf-8'}, []]
|
@@ -131,12 +149,14 @@ module Tanuki
|
|
131
149
|
else
|
132
150
|
[404, {'Content-Type' => 'text/html; charset=utf-8'}, build_body(result[:controller], request_ctx)]
|
133
151
|
end
|
134
|
-
|
152
|
+
|
153
|
+
end # if
|
154
|
+
|
135
155
|
end
|
136
156
|
end
|
137
157
|
|
138
|
-
end #
|
158
|
+
end # class << self
|
139
159
|
|
140
|
-
end #
|
160
|
+
end # Application
|
141
161
|
|
142
|
-
end #
|
162
|
+
end # Tanuki
|
data/lib/tanuki/argument/base.rb
CHANGED