rory 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +18 -0
- data/lib/rory.rb +19 -0
- data/lib/rory/application.rb +110 -0
- data/lib/rory/controller.rb +65 -0
- data/lib/rory/dispatcher.rb +72 -0
- data/lib/rory/route_mapper.rb +35 -0
- data/lib/rory/support.rb +29 -0
- data/lib/rory/tasks.rb +4 -0
- data/lib/rory/version.rb +3 -0
- data/lib/tasks/db.rake +61 -0
- data/lib/tasks/rory.rake +16 -0
- data/rory.gemspec +41 -0
- data/spec/application_spec.rb +116 -0
- data/spec/controller_spec.rb +125 -0
- data/spec/dispatcher_spec.rb +139 -0
- data/spec/fixture_app/config/application.rb +4 -0
- data/spec/fixture_app/config/routes.rb +6 -0
- data/spec/fixture_app/controllers/stub_controller.rb +10 -0
- data/spec/fixture_app/views/layouts/surround.html.erb +1 -0
- data/spec/fixture_app/views/test/dynamic.html.erb +1 -0
- data/spec/fixture_app/views/test/letsgo.html.erb +1 -0
- data/spec/fixture_app/views/test/static.html.erb +1 -0
- data/spec/rory_spec.rb +15 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support_spec.rb +27 -0
- metadata +213 -0
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2013 Ravi Gadad
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
= rory
|
2
|
+
|
3
|
+
The Little Framework That Could, but why?
|
4
|
+
|
5
|
+
== Contributing to rory
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
9
|
+
* Fork the project.
|
10
|
+
* Start a feature/bugfix branch.
|
11
|
+
* Commit and push until you are happy with your contribution.
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
== Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2013 Ravi Gadad. See LICENSE.txt for
|
18
|
+
further details.
|
19
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
5
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'reek/rake/task'
|
9
|
+
Reek::Rake::Task.new do |t|
|
10
|
+
t.fail_on_error = true
|
11
|
+
t.verbose = false
|
12
|
+
t.source_files = 'lib/**/*.rb'
|
13
|
+
end
|
14
|
+
|
15
|
+
task :default => :spec
|
16
|
+
|
17
|
+
require 'yard'
|
18
|
+
YARD::Rake::YardocTask.new
|
data/lib/rory.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
ENV['RORY_STAGE'] ||= ENV['RACK_ENV'] || 'development'
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'sequel'
|
5
|
+
require 'rory/application'
|
6
|
+
require 'rory/dispatcher'
|
7
|
+
require 'rory/support'
|
8
|
+
require 'rory/controller'
|
9
|
+
|
10
|
+
module Rory
|
11
|
+
class << self
|
12
|
+
attr_accessor :application
|
13
|
+
|
14
|
+
def root
|
15
|
+
app = application
|
16
|
+
app && app.root
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'logger'
|
3
|
+
require 'rory/route_mapper'
|
4
|
+
|
5
|
+
module Rory
|
6
|
+
# Main application superclass. Applications should subclass this class,
|
7
|
+
# but currently no additional configuration is needed - just run '#spin_up'
|
8
|
+
# to connect the database so Sequel can do its magic.
|
9
|
+
class Application
|
10
|
+
# Exception raised if no root has been set for this Rory::Application subclass
|
11
|
+
class RootNotConfigured < StandardError; end
|
12
|
+
|
13
|
+
attr_reader :db, :db_config
|
14
|
+
attr_accessor :config_path
|
15
|
+
|
16
|
+
class << self
|
17
|
+
private :new
|
18
|
+
attr_reader :root
|
19
|
+
|
20
|
+
def inherited(base)
|
21
|
+
super
|
22
|
+
Rory.application = base.instance
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(*args, &block)
|
26
|
+
instance.send(*args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def respond_to?(method)
|
30
|
+
return true if instance.respond_to?(method)
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def instance
|
35
|
+
@instance ||= new
|
36
|
+
end
|
37
|
+
|
38
|
+
def root=(root_path)
|
39
|
+
@root = Pathname.new(root_path).expand_path
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def autoload_paths
|
44
|
+
@autoload_paths ||= %w(models controllers helpers)
|
45
|
+
end
|
46
|
+
|
47
|
+
def autoload_all_files
|
48
|
+
autoload_paths.each do |path|
|
49
|
+
Rory::Support.autoload_all_files_in_directory root_path.join(path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def root
|
54
|
+
self.class.root
|
55
|
+
end
|
56
|
+
|
57
|
+
def root_path
|
58
|
+
root || raise(RootNotConfigured, "#{self.class.name} has no root configured")
|
59
|
+
end
|
60
|
+
|
61
|
+
def config_path
|
62
|
+
@config_path ||= begin
|
63
|
+
root_path.join('config')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def set_routes(&block)
|
68
|
+
@routes = RouteMapper.set_routes(&block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def routes
|
72
|
+
unless @routes
|
73
|
+
load(File.join(config_path, 'routes.rb'))
|
74
|
+
end
|
75
|
+
@routes
|
76
|
+
end
|
77
|
+
|
78
|
+
def configure
|
79
|
+
yield self
|
80
|
+
end
|
81
|
+
|
82
|
+
def spin_up
|
83
|
+
connect_db
|
84
|
+
end
|
85
|
+
|
86
|
+
def load_config_data(config_type)
|
87
|
+
YAML.load_file(
|
88
|
+
File.expand_path(File.join(config_path, "#{config_type}.yml"))
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
def connect_db(environment = ENV['RORY_STAGE'])
|
93
|
+
@db_config = load_config_data(:database)
|
94
|
+
@db = Sequel.connect(@db_config[environment.to_s])
|
95
|
+
@db.loggers << logger
|
96
|
+
end
|
97
|
+
|
98
|
+
def call(env)
|
99
|
+
Rory::Dispatcher.new(Rack::Request.new(env), self).dispatch
|
100
|
+
end
|
101
|
+
|
102
|
+
def logger
|
103
|
+
@logger ||= begin
|
104
|
+
Dir.mkdir('log') unless File.exists?('log')
|
105
|
+
file = File.open(File.join('log', "#{ENV['RORY_STAGE']}.log"), 'a')
|
106
|
+
Logger.new(file)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module Rory
|
4
|
+
# Interface for Controller class. Subclass this to create controllers
|
5
|
+
# with actions that will be called by the Dispatcher when a route matches.
|
6
|
+
class Controller
|
7
|
+
def initialize(request, context = nil)
|
8
|
+
@request = request
|
9
|
+
@route = request[:route]
|
10
|
+
@params = request.params
|
11
|
+
@context = context
|
12
|
+
end
|
13
|
+
|
14
|
+
def route_template
|
15
|
+
"#{@route[:controller]}/#{@route[:action]}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def layout
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def render(template, opts = {})
|
23
|
+
opts = { :layout => layout }.merge(opts)
|
24
|
+
file = view_path(template)
|
25
|
+
output = ERB.new(File.read(file)).result(binding)
|
26
|
+
if layout = opts[:layout]
|
27
|
+
output = render(File.join('layouts', layout.to_s), { :layout => false }) { output }
|
28
|
+
end
|
29
|
+
@body = output
|
30
|
+
end
|
31
|
+
|
32
|
+
def view_path(template)
|
33
|
+
root = @context ? @context.root : Rory.root
|
34
|
+
File.expand_path(File.join('views', "#{template}.html.erb"), root)
|
35
|
+
end
|
36
|
+
|
37
|
+
def redirect(path)
|
38
|
+
@response = @request[:dispatcher].redirect(path)
|
39
|
+
end
|
40
|
+
|
41
|
+
def render_not_found
|
42
|
+
@response = @request[:dispatcher].render_not_found
|
43
|
+
end
|
44
|
+
|
45
|
+
def present
|
46
|
+
# if a method exists on the controller for the requested action, call it.
|
47
|
+
action = @route[:action]
|
48
|
+
self.send(action) if self.respond_to?(action)
|
49
|
+
|
50
|
+
if @response
|
51
|
+
# that method may have resulted in a response already being generated
|
52
|
+
# (such as a redirect, or 404, or other non-HTML response). if so,
|
53
|
+
# just return that response.
|
54
|
+
@response
|
55
|
+
else
|
56
|
+
# even if there wasn't a full response generated, we might already have
|
57
|
+
# a @body, if render was explicitly called to render an alternate
|
58
|
+
# template, or if @body was explicitly assigned for some other reason.
|
59
|
+
# don't render the default template, in that case.
|
60
|
+
@body ||= render(route_template)
|
61
|
+
[200, {'Content-type' => 'text/html', 'charset' => 'UTF-8'}, [@body]]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Rory
|
2
|
+
# The dispatcher takes care of sending an incoming request to the
|
3
|
+
# appropriate controller, after examining the routes.
|
4
|
+
class Dispatcher
|
5
|
+
attr_reader :request
|
6
|
+
def initialize(rack_request, context = nil)
|
7
|
+
@request = rack_request
|
8
|
+
@request[:route] ||= nil
|
9
|
+
@request[:dispatcher] = self
|
10
|
+
@context = context
|
11
|
+
end
|
12
|
+
|
13
|
+
def route_map
|
14
|
+
@context ? @context.routes : []
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_route
|
18
|
+
match = nil
|
19
|
+
route = route_map.detect do |route_hash|
|
20
|
+
match = route_hash[:regex].match(@request.path_info[1..-1])
|
21
|
+
methods = route_hash[:methods] || []
|
22
|
+
match && (methods.empty? || methods.include?(method.to_sym))
|
23
|
+
end
|
24
|
+
if route
|
25
|
+
symbolized_param_names = match.names.map { |name| name.to_sym }
|
26
|
+
@request.params.merge! Hash[symbolized_param_names.zip(match.captures)]
|
27
|
+
end
|
28
|
+
route
|
29
|
+
end
|
30
|
+
|
31
|
+
def dispatch
|
32
|
+
route = set_route_if_empty
|
33
|
+
|
34
|
+
if route
|
35
|
+
controller_name = Rory::Support.camelize("#{route[:controller]}_controller")
|
36
|
+
controller_class = Object.const_get(controller_name)
|
37
|
+
controller_class.new(@request, @context).present
|
38
|
+
else
|
39
|
+
render_not_found
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_route_if_empty
|
44
|
+
@request[:route] ||= get_route
|
45
|
+
end
|
46
|
+
|
47
|
+
def method
|
48
|
+
override_method = @request.params.delete('_method')
|
49
|
+
method = if override_method && ['put', 'patch', 'delete'].include?(override_method.downcase)
|
50
|
+
override_method
|
51
|
+
else
|
52
|
+
@request.request_method
|
53
|
+
end
|
54
|
+
method.downcase
|
55
|
+
end
|
56
|
+
|
57
|
+
def redirect(path = '/')
|
58
|
+
unless path =~ /\:\/\//
|
59
|
+
path = "#{@request.scheme}://#{@request.host_with_port}#{path}"
|
60
|
+
end
|
61
|
+
return [ 302, {'Content-type' => 'text/html', 'Location'=> path }, ['Redirecting...'] ]
|
62
|
+
end
|
63
|
+
|
64
|
+
def render_not_found
|
65
|
+
return [ 404, {'Content-type' => 'text/html' }, ['Four, oh, four.'] ]
|
66
|
+
end
|
67
|
+
|
68
|
+
def inspect
|
69
|
+
@request.inspect # fixes issue for rspec and pretty_print
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Rory
|
2
|
+
# Route mapper, used to convert the entries in 'config/routes.rb' into
|
3
|
+
# a routing table for use by the dispatcher.
|
4
|
+
class RouteMapper
|
5
|
+
class << self
|
6
|
+
def set_routes(&block)
|
7
|
+
mapper = new
|
8
|
+
mapper.instance_exec(&block)
|
9
|
+
mapper.routing_map
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@routes = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def routing_map
|
18
|
+
@routes
|
19
|
+
end
|
20
|
+
|
21
|
+
def match(mask, options = {})
|
22
|
+
options[:to] ||= mask.split('/').first
|
23
|
+
mask.gsub!(/^\/$/, '')
|
24
|
+
regex = /^#{mask.gsub(/:([\w_]+)/, "(?<\\1>\[\^\\\/\]+)")}$/
|
25
|
+
controller, action = options[:to].split('#')
|
26
|
+
route = {
|
27
|
+
:controller => controller,
|
28
|
+
:action => action,
|
29
|
+
:regex => regex
|
30
|
+
}
|
31
|
+
route[:methods] = options[:methods] if options[:methods]
|
32
|
+
@routes << route
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/rory/support.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Rory
|
2
|
+
# Support methods for utility functionality such as string modification -
|
3
|
+
# could also be accomplished by monkey-patching String class.
|
4
|
+
module Support
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def camelize(string)
|
8
|
+
string = string.sub(/^[a-z\d]*/) { $&.capitalize }
|
9
|
+
string = string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
|
10
|
+
end
|
11
|
+
|
12
|
+
def extract_class_name_from_path(path)
|
13
|
+
name = File.basename(path).sub(/(.*)\.rb$/, '\1')
|
14
|
+
name = camelize(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def autoload_file(path)
|
18
|
+
path = File.expand_path(path)
|
19
|
+
name = extract_class_name_from_path(path)
|
20
|
+
Object.autoload name.to_sym, path
|
21
|
+
end
|
22
|
+
|
23
|
+
def autoload_all_files_in_directory(path)
|
24
|
+
Dir[Pathname.new(path).join('**', '*.rb')].each do |file|
|
25
|
+
Rory::Support.autoload_file file
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/rory/tasks.rb
ADDED
data/lib/rory/version.rb
ADDED
data/lib/tasks/db.rake
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
namespace :db do
|
2
|
+
task :load_extensions => :environment do
|
3
|
+
RORY_APP.db.extension :schema_dumper
|
4
|
+
Sequel.extension :migration
|
5
|
+
end
|
6
|
+
|
7
|
+
desc "Migrate database to current version (or given version if arg)"
|
8
|
+
task :migrate, [:version] => :load_extensions do |task, args|
|
9
|
+
latest_version = `cd #{File.join(Rory.root, 'db', 'migrate')} && ls -1 [0-9]*_*.rb | tail -1 | sed -e s/_.*$//`
|
10
|
+
args.with_defaults(:version => latest_version)
|
11
|
+
migration_dir = File.join(Rory.root, 'db', 'migrate')
|
12
|
+
Sequel::Migrator.run(RORY_APP.db, migration_dir, :target => args[:version].to_i)
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Drop and recreate a database"
|
16
|
+
task :purge => :load_extensions do
|
17
|
+
config = RORY_APP.db_config[ENV['RORY_STAGE']]
|
18
|
+
drop_database_from_config(config)
|
19
|
+
create_database_from_config(config)
|
20
|
+
end
|
21
|
+
|
22
|
+
namespace :schema do
|
23
|
+
desc "Dump schema from database into db/schema.rb"
|
24
|
+
task :dump => :load_extensions do
|
25
|
+
migration = RORY_APP.db.dump_schema_migration
|
26
|
+
schema_file = File.join(Rory.root, 'db', 'schema.rb')
|
27
|
+
File.open(schema_file, 'w') { |f| f.write migration }
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Loads schema from db/schema.rb into current environment's DB"
|
31
|
+
task :load => :load_extensions do
|
32
|
+
schema_file = File.read(File.join(Rory.root, 'db', 'schema.rb'))
|
33
|
+
eval(schema_file).apply(RORY_APP.db, :up)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
namespace :test do
|
38
|
+
desc "Loads db/schema.rb into test database"
|
39
|
+
task :load => [:load_extensions, :purge] do
|
40
|
+
RORY_APP.connect_db('test')
|
41
|
+
Rake::Task["db:schema:load"].invoke
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Purges test database"
|
45
|
+
task :purge => :load_extensions do
|
46
|
+
ENV['RORY_STAGE'] = 'test'
|
47
|
+
Rake::Task["db:purge"].invoke
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "Recreates empty test database from development's schema"
|
51
|
+
task :prepare => ['db:schema:dump', 'db:test:load']
|
52
|
+
end
|
53
|
+
|
54
|
+
def drop_database_from_config(config)
|
55
|
+
RORY_APP.db << "DROP DATABASE IF EXISTS \"#{config['database']}\""
|
56
|
+
end
|
57
|
+
|
58
|
+
def create_database_from_config(config)
|
59
|
+
RORY_APP.db << "CREATE DATABASE \"#{config['database']}\""
|
60
|
+
end
|
61
|
+
end
|
data/lib/tasks/rory.rake
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
namespace :log do
|
2
|
+
desc "Truncates all logs"
|
3
|
+
task :clear do
|
4
|
+
FileList[File.join('log', '*.log')].each do |file|
|
5
|
+
File.open(file, 'w').close
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Shows all rake tasks and their locations"
|
11
|
+
task :tasks do
|
12
|
+
tasks = Rake.application.tasks.map { |t|
|
13
|
+
{ 'name' => t.name, 'location' => t.locations }
|
14
|
+
}
|
15
|
+
puts tasks
|
16
|
+
end
|
data/rory.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
|
5
|
+
require 'rory/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = "rory"
|
9
|
+
s.version = Rory::VERSION
|
10
|
+
s.platform = Gem::Platform::RUBY
|
11
|
+
s.authors = ["Ravi Gadad"]
|
12
|
+
s.email = ["ravi@screamingmuse.com"]
|
13
|
+
s.homepage = "http://github.com/screamingmuse/rory"
|
14
|
+
s.summary = "Another Ruby web framework. Just what the world needs."
|
15
|
+
s.description = <<-EOF
|
16
|
+
An exercise: Untangle the collusion of Rails idioms
|
17
|
+
from my Ruby knowledge, while trying to understand some
|
18
|
+
Rails design decisions.
|
19
|
+
|
20
|
+
See http://github.com/screamingmuse/rory for more info.
|
21
|
+
EOF
|
22
|
+
s.required_ruby_version = ">= 1.8.7"
|
23
|
+
s.required_rubygems_version = ">= 1.3.6"
|
24
|
+
|
25
|
+
s.extra_rdoc_files = ["LICENSE.txt", "README.rdoc"]
|
26
|
+
s.files = Dir['{lib/**/*,spec/**/*}'] +
|
27
|
+
%w(LICENSE.txt Rakefile README.rdoc rory.gemspec)
|
28
|
+
s.licenses = ["MIT"]
|
29
|
+
s.require_paths = ["lib"]
|
30
|
+
|
31
|
+
s.add_runtime_dependency 'rack', '>= 1.0'
|
32
|
+
s.add_runtime_dependency 'sequel', '~> 4.5'
|
33
|
+
s.add_runtime_dependency 'thin', '~> 1.6'
|
34
|
+
|
35
|
+
s.add_development_dependency 'rake'
|
36
|
+
s.add_development_dependency 'rspec'
|
37
|
+
s.add_development_dependency 'yard'
|
38
|
+
s.add_development_dependency 'reek'
|
39
|
+
s.add_development_dependency 'bundler', '~> 1.0'
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rory::Application do
|
4
|
+
describe ".configure" do
|
5
|
+
it 'yields the given block to self' do
|
6
|
+
Fixture::Application.configure do |c|
|
7
|
+
c.should == Fixture::Application.instance
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.config_path' do
|
13
|
+
it 'is set to {root}/config by default' do
|
14
|
+
Fixture::Application.config_path.should ==
|
15
|
+
Pathname.new(Fixture::Application.root).join('config')
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'raises exception if root not set' do
|
19
|
+
Rory.application = nil
|
20
|
+
class RootlessApp < Rory::Application; end
|
21
|
+
expect {
|
22
|
+
RootlessApp.config_path
|
23
|
+
}.to raise_error(RootlessApp::RootNotConfigured)
|
24
|
+
Rory.application = Fixture::Application.instance
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe ".respond_to?" do
|
29
|
+
it 'returns true if the instance said so' do
|
30
|
+
Fixture::Application.instance.should_receive(:respond_to?).with(:goat).and_return(true)
|
31
|
+
Fixture::Application.respond_to?(:goat).should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'does the usual thing if instance says no' do
|
35
|
+
Fixture::Application.instance.should_receive(:respond_to?).twice.and_return(false)
|
36
|
+
Fixture::Application.respond_to?(:to_s).should be_true
|
37
|
+
Fixture::Application.respond_to?(:obviously_not_a_real_method).should be_false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe ".call" do
|
42
|
+
it "forwards arg to new dispatcher, and calls dispatch" do
|
43
|
+
dispatcher = stub(:dispatch => :expected)
|
44
|
+
rack_request = double
|
45
|
+
Rack::Request.stub(:new).with(:env).and_return(rack_request)
|
46
|
+
Rory::Dispatcher.should_receive(:new).with(rack_request, Fixture::Application.instance).and_return(dispatcher)
|
47
|
+
Fixture::Application.call(:env).should == :expected
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
describe ".load_config_data" do
|
52
|
+
it "returns parsed yaml file with given name from directory at config_path" do
|
53
|
+
Fixture::Application.any_instance.stub(:config_path).and_return('Africa the Great')
|
54
|
+
YAML.stub!(:load_file).with(
|
55
|
+
File.expand_path(File.join('Africa the Great', 'foo_type.yml'))).
|
56
|
+
and_return(:oscar_the_grouch_takes_a_nap)
|
57
|
+
Fixture::Application.load_config_data(:foo_type).should == :oscar_the_grouch_takes_a_nap
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe ".connect_db" do
|
62
|
+
it "sets up sequel connection to DB from YAML file" do
|
63
|
+
config = { 'development' => :expected }
|
64
|
+
Fixture::Application.any_instance.stub(:load_config_data).with(:database).and_return(config)
|
65
|
+
Sequel.should_receive(:connect).with(:expected).and_return(stub(:loggers => []))
|
66
|
+
Fixture::Application.connect_db('development')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ".routes" do
|
71
|
+
it "generates a routing table from route configuration" do
|
72
|
+
# note: we're comparing the inspected arrays here because the arrays
|
73
|
+
# won't be equal, despite appearing the same - this is because the Regexes
|
74
|
+
# are different objects.
|
75
|
+
Fixture::Application.routes.inspect.should == [
|
76
|
+
{ :controller => 'foo', :action => 'bar', :regex => /^foo\/(?<id>[^\/]+)\/bar$/, :methods => [:get, :post] },
|
77
|
+
{ :controller => 'monkeys', :action => nil, :regex => /^foo$/, :methods => [:put] },
|
78
|
+
{ :controller => 'awesome', :action => 'rad', :regex => /^this\/(?<path>[^\/]+)\/is\/(?<very_awesome>[^\/]+)$/},
|
79
|
+
{ :controller => 'root', :action => 'vegetable', :regex => /^$/, :methods => [:get] }
|
80
|
+
].inspect
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe ".spin_up" do
|
85
|
+
it "connects the database" do
|
86
|
+
Rory::Application.any_instance.should_receive(:connect_db)
|
87
|
+
Rory::Application.spin_up
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '.autoload_paths' do
|
92
|
+
after(:each) do
|
93
|
+
Fixture::Application.instance.instance_variable_set(:@autoload_paths, nil)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'includes models, controllers, and helpers by default' do
|
97
|
+
Fixture::Application.autoload_paths.should == ['models', 'controllers', 'helpers']
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'accepts new paths' do
|
101
|
+
Fixture::Application.autoload_paths << 'chocolates'
|
102
|
+
Fixture::Application.autoload_paths.should == ['models', 'controllers', 'helpers', 'chocolates']
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '.autoload_all_files' do
|
107
|
+
it 'autoloads all files in autoload_paths' do
|
108
|
+
Fixture::Application.any_instance.stub(:autoload_paths).and_return(['goats', 'rhubarbs'])
|
109
|
+
[:goats, :rhubarbs].each do |folder|
|
110
|
+
Rory::Support.should_receive(:autoload_all_files_in_directory).
|
111
|
+
with(Pathname.new(Fixture::Application.root).join("#{folder}"))
|
112
|
+
end
|
113
|
+
Fixture::Application.autoload_all_files
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rory::Controller do
|
4
|
+
before :each do
|
5
|
+
@request = {
|
6
|
+
:route => {
|
7
|
+
:controller => 'test',
|
8
|
+
:action => 'letsgo'
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
@request.stub(:params => {})
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#layout' do
|
16
|
+
it 'defaults to nil' do
|
17
|
+
controller = Rory::Controller.new(@request)
|
18
|
+
controller.layout.should be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#render" do
|
23
|
+
it "returns text of template" do
|
24
|
+
controller = Rory::Controller.new(@request)
|
25
|
+
controller.render('test/static').should == 'Static content'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns text of template in controller's layout" do
|
29
|
+
controller = Rory::Controller.new(@request)
|
30
|
+
controller.stub(:layout => 'surround')
|
31
|
+
controller.render('test/static').should == 'Surrounding Static content is fun'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "handles symbolized layout name" do
|
35
|
+
controller = Rory::Controller.new(@request)
|
36
|
+
controller.stub(:layout => :surround)
|
37
|
+
controller.render('test/static').should == 'Surrounding Static content is fun'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns text of template in given layout from options" do
|
41
|
+
controller = Rory::Controller.new(@request)
|
42
|
+
controller.render('test/static', :layout => 'surround').should == 'Surrounding Static content is fun'
|
43
|
+
end
|
44
|
+
|
45
|
+
it "evaluates ERB in controller's context" do
|
46
|
+
controller = Rory::Controller.new(@request)
|
47
|
+
controller.stub(:word).and_return('hockey')
|
48
|
+
controller.render('test/dynamic').should == 'Word: hockey'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#redirect" do
|
53
|
+
it "delegates to dispatcher from request" do
|
54
|
+
@request[:dispatcher] = dispatcher = stub
|
55
|
+
dispatcher.should_receive(:redirect).with(:whatever)
|
56
|
+
controller = Rory::Controller.new(@request)
|
57
|
+
controller.redirect(:whatever)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#render_not_found" do
|
62
|
+
it "delegates to dispatcher from request" do
|
63
|
+
@request[:dispatcher] = dispatcher = stub
|
64
|
+
dispatcher.should_receive(:render_not_found)
|
65
|
+
controller = Rory::Controller.new(@request)
|
66
|
+
controller.render_not_found
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#present" do
|
71
|
+
it "calls action from route if exists on controller" do
|
72
|
+
controller = Rory::Controller.new(@request)
|
73
|
+
controller.stub(:render)
|
74
|
+
controller.should_receive('letsgo')
|
75
|
+
controller.present
|
76
|
+
end
|
77
|
+
|
78
|
+
it "doesn't try to call action from route if nonexistent on controller" do
|
79
|
+
controller = Rory::Controller.new(@request)
|
80
|
+
controller.stub(:render)
|
81
|
+
controller.stub(:respond_to?).with('letsgo').and_return(false)
|
82
|
+
controller.should_receive('letsgo').never
|
83
|
+
controller.present
|
84
|
+
end
|
85
|
+
|
86
|
+
it "just returns a response if @response exists" do
|
87
|
+
controller = Rory::Controller.new(@request)
|
88
|
+
controller.instance_variable_set(:@response, 'Forced response')
|
89
|
+
controller.present.should == 'Forced response'
|
90
|
+
end
|
91
|
+
|
92
|
+
it "renders and returns the default template as a rack response" do
|
93
|
+
controller = Rory::Controller.new(@request)
|
94
|
+
controller.present.should == [
|
95
|
+
200,
|
96
|
+
{'Content-type' => 'text/html', 'charset' => 'UTF-8'},
|
97
|
+
["Let's go content"]
|
98
|
+
]
|
99
|
+
end
|
100
|
+
|
101
|
+
it "returns previously set @body as a rack response" do
|
102
|
+
controller = Rory::Controller.new(@request)
|
103
|
+
controller.instance_variable_set(:@body, 'Forced body')
|
104
|
+
controller.should_receive(:render).never
|
105
|
+
controller.present.should == [
|
106
|
+
200,
|
107
|
+
{'Content-type' => 'text/html', 'charset' => 'UTF-8'},
|
108
|
+
["Forced body"]
|
109
|
+
]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#view_path' do
|
114
|
+
it 'returns path to template from context root' do
|
115
|
+
fake_context = double('Context', :root => 'marbles')
|
116
|
+
controller = Rory::Controller.new(@request, fake_context)
|
117
|
+
controller.view_path('goose').should == File.expand_path(File.join('views', 'goose.html.erb'), 'marbles')
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'uses Rory.root if no context' do
|
121
|
+
controller = Rory::Controller.new(@request)
|
122
|
+
controller.view_path('goose').should == File.join(Rory.root, 'views', 'goose.html.erb')
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rory::Dispatcher do
|
4
|
+
describe "#redirect" do
|
5
|
+
it "redirects to given path if path has scheme" do
|
6
|
+
dispatcher = Rory::Dispatcher.new({}, Fixture::Application)
|
7
|
+
redirection = dispatcher.redirect('http://example.example')
|
8
|
+
redirection[0..1].should == [
|
9
|
+
302, {'Content-type' => 'text/html', 'Location'=> 'http://example.example' }
|
10
|
+
]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "adds request host and scheme and redirects if path has no scheme" do
|
14
|
+
request = {}
|
15
|
+
request.stub('scheme' => 'happy', 'host_with_port' => 'somewhere.yay')
|
16
|
+
dispatcher = Rory::Dispatcher.new(request, Fixture::Application)
|
17
|
+
redirection = dispatcher.redirect('/example')
|
18
|
+
redirection[0..1].should == [
|
19
|
+
302, {'Content-type' => 'text/html', 'Location'=> 'happy://somewhere.yay/example' }
|
20
|
+
]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#dispatch" do
|
25
|
+
it "renders a 404 if the requested path is invalid" do
|
26
|
+
@request = {}
|
27
|
+
@request.stub(:path_info => nil, :request_method => 'GET', :params => {})
|
28
|
+
@dispatcher = Rory::Dispatcher.new(@request, Fixture::Application)
|
29
|
+
@dispatcher.stub(:get_route).and_return(nil)
|
30
|
+
@dispatcher.dispatch[0..1].should == [404, {"Content-type"=>"text/html"}]
|
31
|
+
end
|
32
|
+
|
33
|
+
it "instantiates a controller with the parsed request and calls present" do
|
34
|
+
@request = {:whatever => :yay}
|
35
|
+
@request.stub(:path_info => '/', :request_method => 'GET', :params => {})
|
36
|
+
@dispatcher = Rory::Dispatcher.new(@request, Fixture::Application)
|
37
|
+
route = { :controller => 'stub' }
|
38
|
+
@dispatcher.stub(:get_route).and_return(route)
|
39
|
+
@dispatcher.dispatch.should == {
|
40
|
+
:whatever => :yay,
|
41
|
+
:route => route,
|
42
|
+
:dispatcher => @dispatcher,
|
43
|
+
:present_called => true # see StubController in /spec/fixture_app
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
it "uses existing route if given in request" do
|
48
|
+
@request = {:whatever => :yay, :route => { :controller => 'stub' } }
|
49
|
+
@request.stub(:path_info => '/', :request_method => 'GET', :params => {})
|
50
|
+
@dispatcher = Rory::Dispatcher.new(@request, Fixture::Application)
|
51
|
+
@dispatcher.should_receive(:get_route).never
|
52
|
+
@dispatcher.dispatch.should == {
|
53
|
+
:whatever => :yay,
|
54
|
+
:route => { :controller => 'stub' },
|
55
|
+
:dispatcher => @dispatcher,
|
56
|
+
:present_called => true # see StubController in /spec/fixture_app
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#get_route" do
|
62
|
+
before(:each) do
|
63
|
+
@request = {}
|
64
|
+
@request.stub(:params => {})
|
65
|
+
@dispatcher = Rory::Dispatcher.new(@request, Fixture::Application)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "matches the path from the request to the routes table" do
|
69
|
+
@request.stub(:path_info => '/foo', :request_method => 'PUT')
|
70
|
+
@dispatcher.get_route.should == {
|
71
|
+
:controller => 'monkeys',
|
72
|
+
:action => nil,
|
73
|
+
:regex => /^foo$/,
|
74
|
+
:methods => [:put]
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
it "works with root url represented by slash" do
|
79
|
+
@request.stub(:path_info => '/', :request_method => 'GET')
|
80
|
+
@dispatcher.get_route.should == {
|
81
|
+
:controller => 'root',
|
82
|
+
:action => 'vegetable',
|
83
|
+
:regex => /^$/,
|
84
|
+
:methods => [:get]
|
85
|
+
}
|
86
|
+
end
|
87
|
+
|
88
|
+
it "returns nil if no route found" do
|
89
|
+
@request.stub(:path_info => '/umbrellas', :request_method => 'GET')
|
90
|
+
@dispatcher.get_route.should be_nil
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns nil if no context" do
|
94
|
+
@dispatcher = Rory::Dispatcher.new(@request)
|
95
|
+
@dispatcher.get_route.should be_nil
|
96
|
+
end
|
97
|
+
|
98
|
+
it "returns nil if route found but method is not allowed" do
|
99
|
+
@request.stub(:path_info => '/foo', :request_method => 'GET')
|
100
|
+
@dispatcher.get_route.should be_nil
|
101
|
+
end
|
102
|
+
|
103
|
+
it "assigns named matches to params hash" do
|
104
|
+
@request.stub(:path_info => '/this/some-thing_or-other/is/wicked', :request_method => 'GET')
|
105
|
+
@dispatcher.get_route.inspect.should == {
|
106
|
+
:controller => 'awesome',
|
107
|
+
:action => 'rad',
|
108
|
+
:regex => /^this\/(?<path>[^\/]+)\/is\/(?<very_awesome>[^\/]+)$/,
|
109
|
+
}.inspect
|
110
|
+
|
111
|
+
@request.params.should == {:path=>"some-thing_or-other", :very_awesome=>"wicked"}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe '#method' do
|
116
|
+
it 'returns downcased method from request' do
|
117
|
+
request = {:whatever => :yay}
|
118
|
+
request.stub(:path_info => '/', :request_method => 'POST', :params => {})
|
119
|
+
dispatcher = Rory::Dispatcher.new(request, Fixture::Application)
|
120
|
+
dispatcher.method.should == 'post'
|
121
|
+
end
|
122
|
+
|
123
|
+
['put', 'patch', 'delete'].each do |override_method|
|
124
|
+
it "overrides request method if _method from params is #{override_method}" do
|
125
|
+
request = {:whatever => :yay}
|
126
|
+
request.stub(:path_info => '/', :request_method => 'POST', :params => {'_method' => override_method})
|
127
|
+
dispatcher = Rory::Dispatcher.new(request, Fixture::Application)
|
128
|
+
dispatcher.method.should == override_method
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'ignores overriding _method if not valid' do
|
133
|
+
request = {:whatever => :yay}
|
134
|
+
request.stub(:path_info => '/', :request_method => 'POST', :params => {'_method' => 'rhubarb'})
|
135
|
+
dispatcher = Rory::Dispatcher.new(request, Fixture::Application)
|
136
|
+
dispatcher.method.should == 'post'
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Fixture::Application.set_routes do
|
2
|
+
match 'foo/:id/bar', :to => 'foo#bar', :methods => [:get, :post]
|
3
|
+
match 'foo', :to => 'monkeys', :methods => [:put]
|
4
|
+
match 'this/:path/is/:very_awesome', :to => 'awesome#rad'
|
5
|
+
match '/', :to => 'root#vegetable', :methods => [:get]
|
6
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Surrounding <%= yield %> is fun
|
@@ -0,0 +1 @@
|
|
1
|
+
Word: <%= word %>
|
@@ -0,0 +1 @@
|
|
1
|
+
Let's go content
|
@@ -0,0 +1 @@
|
|
1
|
+
Static content
|
data/spec/rory_spec.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rory do
|
4
|
+
describe '.application' do
|
5
|
+
it 'is by default set to the Rory::Application instance' do
|
6
|
+
Rory.application.should == Fixture::Application.instance
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.root' do
|
11
|
+
it 'returns root of application' do
|
12
|
+
Rory.root.should == Rory.application.root
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
ENV['RORY_STAGE'] = 'test'
|
2
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
3
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
4
|
+
require 'rspec'
|
5
|
+
require 'rory'
|
6
|
+
require 'rack'
|
7
|
+
|
8
|
+
# Requires supporting files with custom matchers and macros, etc,
|
9
|
+
# in ./support/ and its subdirectories.
|
10
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
11
|
+
|
12
|
+
require_relative 'fixture_app/config/application'
|
13
|
+
Fixture::Application.root = File.join(File.dirname(__FILE__), 'fixture_app')
|
14
|
+
|
15
|
+
Fixture::Application.autoload_all_files
|
16
|
+
|
17
|
+
RSpec.configure do |config|
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rory::Support do
|
4
|
+
describe ".camelize" do
|
5
|
+
it "camelizes given snake-case string" do
|
6
|
+
Rory::Support.camelize('water_under_bridge').should == 'WaterUnderBridge'
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.autoload_file' do
|
11
|
+
it 'adds basename of given path to autoload list by default' do
|
12
|
+
path = '/fake_root/gas/is/cheap/in/good_old_america.rb'
|
13
|
+
Object.should_receive(:autoload).with(:GoodOldAmerica, path)
|
14
|
+
Rory::Support.autoload_file(path)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.autoload_all_files_in_directory' do
|
19
|
+
it 'autoloads all files from given path' do
|
20
|
+
Dir.stub(:[]).with(Pathname.new('spinach').join('**', '*.rb')).
|
21
|
+
and_return(["pumpkins", "some_guy_dressed_as_liberace"])
|
22
|
+
Rory::Support.should_receive(:autoload_file).with("pumpkins")
|
23
|
+
Rory::Support.should_receive(:autoload_file).with("some_guy_dressed_as_liberace")
|
24
|
+
Rory::Support.autoload_all_files_in_directory('spinach')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ravi Gadad
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-01-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sequel
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '4.5'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '4.5'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: thin
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.6'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: yard
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: reek
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: bundler
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '1.0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '1.0'
|
142
|
+
description: ! 'An exercise: Untangle the collusion of Rails idioms
|
143
|
+
|
144
|
+
from my Ruby knowledge, while trying to understand some
|
145
|
+
|
146
|
+
Rails design decisions.
|
147
|
+
|
148
|
+
|
149
|
+
See http://github.com/screamingmuse/rory for more info.
|
150
|
+
|
151
|
+
'
|
152
|
+
email:
|
153
|
+
- ravi@screamingmuse.com
|
154
|
+
executables: []
|
155
|
+
extensions: []
|
156
|
+
extra_rdoc_files:
|
157
|
+
- LICENSE.txt
|
158
|
+
- README.rdoc
|
159
|
+
files:
|
160
|
+
- lib/rory/application.rb
|
161
|
+
- lib/rory/controller.rb
|
162
|
+
- lib/rory/dispatcher.rb
|
163
|
+
- lib/rory/route_mapper.rb
|
164
|
+
- lib/rory/support.rb
|
165
|
+
- lib/rory/tasks.rb
|
166
|
+
- lib/rory/version.rb
|
167
|
+
- lib/rory.rb
|
168
|
+
- lib/tasks/db.rake
|
169
|
+
- lib/tasks/rory.rake
|
170
|
+
- spec/application_spec.rb
|
171
|
+
- spec/controller_spec.rb
|
172
|
+
- spec/dispatcher_spec.rb
|
173
|
+
- spec/fixture_app/config/application.rb
|
174
|
+
- spec/fixture_app/config/routes.rb
|
175
|
+
- spec/fixture_app/controllers/stub_controller.rb
|
176
|
+
- spec/fixture_app/views/layouts/surround.html.erb
|
177
|
+
- spec/fixture_app/views/test/dynamic.html.erb
|
178
|
+
- spec/fixture_app/views/test/letsgo.html.erb
|
179
|
+
- spec/fixture_app/views/test/static.html.erb
|
180
|
+
- spec/rory_spec.rb
|
181
|
+
- spec/spec_helper.rb
|
182
|
+
- spec/support_spec.rb
|
183
|
+
- LICENSE.txt
|
184
|
+
- Rakefile
|
185
|
+
- README.rdoc
|
186
|
+
- rory.gemspec
|
187
|
+
homepage: http://github.com/screamingmuse/rory
|
188
|
+
licenses:
|
189
|
+
- MIT
|
190
|
+
post_install_message:
|
191
|
+
rdoc_options: []
|
192
|
+
require_paths:
|
193
|
+
- lib
|
194
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
195
|
+
none: false
|
196
|
+
requirements:
|
197
|
+
- - ! '>='
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: 1.8.7
|
200
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
none: false
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
205
|
+
version: 1.3.6
|
206
|
+
requirements: []
|
207
|
+
rubyforge_project:
|
208
|
+
rubygems_version: 1.8.23
|
209
|
+
signing_key:
|
210
|
+
specification_version: 3
|
211
|
+
summary: Another Ruby web framework. Just what the world needs.
|
212
|
+
test_files: []
|
213
|
+
has_rdoc:
|