rad_core 0.0.25 → 0.0.26
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +3 -1
- data/bin/rad +33 -0
- data/lib/components/configurators.rb +5 -0
- data/lib/components/environment.production.yml +1 -0
- data/lib/components/environment.yml +30 -1
- data/lib/components/http.yml +12 -1
- data/lib/components/web.rb +2 -2
- data/lib/rad/_support/active_support/{micelaneous.rb → miscellaneous.rb} +0 -0
- data/lib/rad/_support/active_support.rb +1 -1
- data/lib/rad/_support/exception.rb +9 -40
- data/lib/rad/_support/string.rb +7 -1
- data/lib/rad/cli/helper.rb +34 -0
- data/lib/rad/configurators/_require.rb +13 -0
- data/lib/rad/configurators/abstract.rb +24 -0
- data/lib/rad/configurators/runtime.rb +4 -0
- data/lib/rad/configurators/web.rb +34 -0
- data/lib/rad/controller/_abstract/{micelaneous.rb → miscellaneous.rb} +1 -1
- data/lib/rad/controller/_abstract/render.rb +54 -53
- data/lib/rad/controller/_abstract.rb +16 -8
- data/lib/rad/controller/_context.rb +3 -9
- data/lib/rad/controller/_http.rb +22 -17
- data/lib/rad/controller/_require.rb +1 -1
- data/lib/rad/controller/processors/controller_caller.rb +5 -13
- data/lib/rad/controller/processors/controller_error_handling.rb +2 -2
- data/lib/rad/environment/_environment.rb +4 -0
- data/lib/rad/environment/_logger.rb +5 -5
- data/lib/rad/html/_require.rb +1 -1
- data/lib/rad/http/_http.rb +8 -4
- data/lib/rad/http/_http_adapter.rb +1 -21
- data/lib/rad/http/_request.rb +48 -7
- data/lib/rad/http/_require.rb +1 -1
- data/lib/rad/http/_response.rb +1 -1
- data/lib/rad/http/_support/rack/fixes.rb +6 -0
- data/lib/rad/http/processors/prepare_params.rb +1 -1
- data/lib/rad/mailer/processors/letter_builder.rb +3 -9
- data/lib/rad/profiles/web.rb +35 -10
- data/lib/rad/router/_router.rb +1 -1
- data/lib/rad/router/{micelaneous_router.rb → miscellaneous_router.rb} +0 -0
- data/lib/rad/spec/http_controller.rb +15 -11
- data/lib/rad/spec/web.rb +7 -0
- data/lib/rad/spec.rb +1 -0
- data/lib/rad/tasks.rb +15 -0
- data/lib/rad/template/_context.rb +0 -4
- data/lib/rad/template/_template.rb +1 -1
- data/lib/rad/web/_ajax_helper.rb +16 -0
- data/lib/rad/{core_web/_controller_micelaneous_helper.rb → web/_controller_miscellaneous_helper.rb} +2 -2
- data/lib/rad/web/_ensure_no_www.rb +30 -0
- data/lib/rad/web/_protect_from_forgery.rb +71 -0
- data/lib/rad/{core_web → web}/_require.rb +13 -4
- data/lib/rad/{core_web → web}/_router/abstract_routing_helper.rb +0 -0
- data/lib/rad/{core_web → web}/_router/controller_routing_helper.rb +0 -0
- data/lib/rad/{core_web → web}/_router/view_routing_helper.rb +0 -0
- data/lib/rad.rb +1 -1
- data/readme.md +14 -7
- data/spec/controller/abstract_spec.rb +2 -2
- data/spec/controller/error_handling_spec.rb +1 -1
- data/spec/controller/http_spec/views/ViewVariablesSpec/action.erb +2 -0
- data/spec/controller/http_spec.rb +18 -1
- data/spec/controller/render_spec.rb +13 -13
- data/spec/http/http_spec.rb +1 -1
- data/spec/http/{micelaneous_spec.rb → miscellaneous_spec.rb} +0 -0
- data/spec/router/integration_spec.rb +4 -1
- data/spec/router/object_router_spec.rb +1 -1
- data/spec/router/persistent_params_spec.rb +1 -1
- data/spec/router/restful_router_spec.rb +1 -1
- data/spec/web/basic_spec.rb +8 -4
- data/spec/web/controller_routing_helper_spec.rb +4 -3
- data/spec/web/flash_spec.rb +2 -3
- data/spec/web/protect_from_forgery_spec.rb +187 -0
- data/spec/web/spec_helper_spec.rb +9 -5
- data/spec/web/view_routing_helper_spec.rb +1 -1
- metadata +27 -12
data/lib/rad/html/_require.rb
CHANGED
data/lib/rad/http/_http.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
class Rad::Http
|
2
|
-
inject environment: :environment
|
3
|
-
attr_reader :rack_adapter, :http_adapter
|
1
|
+
class Rad::Http
|
2
|
+
# inject environment: :environment
|
3
|
+
attr_reader :rack_adapter, :http_adapter
|
4
|
+
|
5
|
+
attr_writer :browser_generated_types, :browser_generated_formats
|
6
|
+
def browser_generated_types; @browser_generated_types ||= [] end
|
7
|
+
def browser_generated_formats; @browser_generated_formats ||= [] end
|
4
8
|
|
5
9
|
def initialize
|
6
10
|
@rack_adapter, @http_adapter = Rad::Http::RackAdapter.new, Rad::Http::HttpAdapter.new
|
7
11
|
end
|
8
12
|
|
9
13
|
delegate :configure_rack!, :stack, :run, to: :rack_adapter
|
10
|
-
delegate :call,
|
14
|
+
delegate :call, to: :http_adapter
|
11
15
|
end
|
@@ -20,25 +20,5 @@ class Rad::Http::HttpAdapter
|
|
20
20
|
# env['rack.input'] ||= StringIO.new
|
21
21
|
#
|
22
22
|
# call env, workspace, &block
|
23
|
-
# end
|
24
|
-
|
25
|
-
def mock_environment url = nil
|
26
|
-
env = {
|
27
|
-
'rack.url_scheme' => 'http',
|
28
|
-
'PATH_INFO' => '/',
|
29
|
-
'HTTP_HOST' => 'spec',
|
30
|
-
'rack.input' => StringIO.new
|
31
|
-
}
|
32
|
-
if url
|
33
|
-
uri = Uri.parse url
|
34
|
-
env.merge!(
|
35
|
-
'HTTP_HOST' => %(#{uri.host}#{":#{uri.port}" if uri.port.present?}),
|
36
|
-
# 'REQUEST_PATH' => uri.path,
|
37
|
-
'PATH_INFO' => uri.path,
|
38
|
-
# 'REQUEST_URI' => uri.path,
|
39
|
-
'QUERY_STRING' => uri.query
|
40
|
-
)
|
41
|
-
end
|
42
|
-
env
|
43
|
-
end
|
23
|
+
# end
|
44
24
|
end
|
data/lib/rad/http/_request.rb
CHANGED
@@ -7,8 +7,7 @@ class Rad::Http::Request < Rack::Request
|
|
7
7
|
# def secure?
|
8
8
|
# (@env['HTTP_X_FORWARDED_PROTO'] || @env['rack.url_scheme']) == 'https'
|
9
9
|
# end
|
10
|
-
|
11
|
-
|
10
|
+
|
12
11
|
# Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
|
13
12
|
# returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
|
14
13
|
# such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
|
@@ -36,11 +35,53 @@ class Rad::Http::Request < Rack::Request
|
|
36
35
|
def normalized_domain
|
37
36
|
return nil unless named_host?(host)
|
38
37
|
host.sub('www.', '').downcase
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
#
|
43
|
-
#
|
38
|
+
end
|
39
|
+
|
40
|
+
def from_browser?
|
41
|
+
# format = workspace.params.format
|
42
|
+
# (format.present? and !rad.http.browser_generated_formats.include?(format)) or
|
43
|
+
content_type.present? and rad.http.browser_generated_types.include?(content_type.downcase)
|
44
|
+
end
|
45
|
+
|
46
|
+
#
|
47
|
+
# Need this to access original, not normalized with Utils.normalize_params params
|
48
|
+
#
|
49
|
+
def raw_params
|
50
|
+
post = {}
|
51
|
+
@env['rack.input'].read.split('&').each do |tuple|
|
52
|
+
k, v = tuple.split('=')
|
53
|
+
post[Rack::Utils.unescape(k || "")] = Rack::Utils.unescape(v || "")
|
54
|
+
end
|
55
|
+
self.GET.merge(post)
|
56
|
+
rescue EOFError
|
57
|
+
self.GET
|
58
|
+
end
|
59
|
+
|
60
|
+
class << self
|
61
|
+
def stub url = '/'
|
62
|
+
env = stub_environment(url)
|
63
|
+
Rad::Http::Request.new env
|
64
|
+
end
|
65
|
+
|
66
|
+
def stub_environment url = nil
|
67
|
+
env = {
|
68
|
+
'rack.url_scheme' => 'http',
|
69
|
+
'PATH_INFO' => '/',
|
70
|
+
'HTTP_HOST' => 'test.com',
|
71
|
+
'rack.input' => StringIO.new
|
72
|
+
}
|
73
|
+
if url
|
74
|
+
uri = Uri.parse url
|
75
|
+
env.merge!(
|
76
|
+
'HTTP_HOST' => %(#{uri.host}#{":#{uri.port}" if uri.port.present?}),
|
77
|
+
# 'REQUEST_PATH' => uri.path,
|
78
|
+
'PATH_INFO' => uri.path,
|
79
|
+
# 'REQUEST_URI' => uri.path,
|
80
|
+
'QUERY_STRING' => uri.query
|
81
|
+
)
|
82
|
+
end
|
83
|
+
env
|
84
|
+
end
|
44
85
|
end
|
45
86
|
|
46
87
|
protected
|
data/lib/rad/http/_require.rb
CHANGED
@@ -6,7 +6,7 @@ require 'rack/builder'
|
|
6
6
|
|
7
7
|
class Rad::Http
|
8
8
|
attr_accessor :host, :port, :static, :url_root, :default_format, :session
|
9
|
-
|
9
|
+
attr_required :host, :port, :url_root, :default_format
|
10
10
|
def static?; !!@static end
|
11
11
|
|
12
12
|
attr_writer :public_path
|
data/lib/rad/http/_response.rb
CHANGED
@@ -19,6 +19,12 @@ class Rack::Request
|
|
19
19
|
def params
|
20
20
|
@params ||= encode_in_utf8(params_with_wrong_encoding)
|
21
21
|
end
|
22
|
+
|
23
|
+
# it returns "application/x-www-form-urlencoded; charset=UTF-8" instead of "application/x-www-form-urlencoded"
|
24
|
+
def content_type_with_fix
|
25
|
+
content_type_without_fix && content_type_without_fix.split(';').first
|
26
|
+
end
|
27
|
+
alias_method_chain :content_type, :fix
|
22
28
|
|
23
29
|
protected
|
24
30
|
def encode_in_utf8 hash
|
@@ -6,7 +6,7 @@ rad.http
|
|
6
6
|
class PrepareParams < Rad::Conveyors::Processor
|
7
7
|
def call
|
8
8
|
workspace.env.must_be.defined
|
9
|
-
workspace.request = Rad::Http::Request.new(workspace.env)
|
9
|
+
workspace.request = Rad::Http::Request.new(workspace.env)
|
10
10
|
workspace.path = workspace.request.path
|
11
11
|
params = workspace.params = Rad::Conveyors::Params.new(workspace.request.params)
|
12
12
|
|
@@ -5,17 +5,11 @@ class LetterBuilder < Rad::Conveyors::Processor
|
|
5
5
|
# prepare
|
6
6
|
controller = workspace.controller.must_be.present
|
7
7
|
raise "The controller #{controller} must be a Rad::Mailer::MailerController!" unless controller.is_a? Rad::Mailer::MailerController
|
8
|
-
|
8
|
+
action_name = workspace.action_name = workspace.method_name
|
9
9
|
|
10
10
|
# call
|
11
|
-
|
12
|
-
|
13
|
-
# call controller
|
14
|
-
controller.send action, *workspace.arguments
|
15
|
-
# render view
|
16
|
-
controller.render action: action
|
17
|
-
end
|
18
|
-
end
|
11
|
+
controller.set! params: workspace.params, action_name: workspace.action_name
|
12
|
+
content = controller.call action_name, *workspace.arguments
|
19
13
|
|
20
14
|
controller.body = content unless content.blank?
|
21
15
|
|
data/lib/rad/profiles/web.rb
CHANGED
@@ -1,7 +1,18 @@
|
|
1
|
+
#
|
2
|
+
# Router
|
3
|
+
#
|
4
|
+
rad.router.routers = [
|
5
|
+
[:alias_router, Rad::Router::AliasRouter.new],
|
6
|
+
[:basic_router, Rad::Router::BasicRouter.new],
|
7
|
+
[:restful_router, Rad::Router::RestfulRouter.new],
|
8
|
+
[:object_router, Rad::Router::ObjectRouter.new]
|
9
|
+
]
|
10
|
+
|
11
|
+
|
1
12
|
#
|
2
13
|
# Conveyors
|
3
14
|
#
|
4
|
-
rad.conveyors.web do |web|
|
15
|
+
rad.conveyors.web do |web|
|
5
16
|
# conveyor
|
6
17
|
web.use Rad::Conveyors::Processors::ConveyorLogger
|
7
18
|
|
@@ -11,35 +22,49 @@ rad.conveyors.web do |web|
|
|
11
22
|
web.use Rad::Http::Processors::EvaluateFormat
|
12
23
|
web.use Rad::Http::Processors::HttpLogger
|
13
24
|
|
25
|
+
# forgery protection
|
26
|
+
web.use Rad::Web::Processors::PrepareAutenticityToken
|
27
|
+
|
28
|
+
# ensure no www
|
29
|
+
web.use Rad::Web::Processors::EnsureNoWww
|
30
|
+
|
31
|
+
# ajax
|
32
|
+
web.use Rad::Web::Processors::AjaxHelper
|
33
|
+
|
14
34
|
# html
|
15
35
|
# web.use ScopedParams
|
16
36
|
web.use Rad::Html::Processors::PrepareFlash
|
17
|
-
|
37
|
+
|
18
38
|
# controller
|
19
39
|
web.use Rad::Controller::Processors::ControllerErrorHandling
|
20
|
-
|
40
|
+
|
21
41
|
# router
|
22
42
|
web.use Rad::Router::Processors::Router, :class, :method_name
|
23
43
|
|
24
44
|
# controller
|
25
45
|
web.use Rad::Controller::Processors::ControllerLogger
|
26
46
|
web.use Rad::Controller::Processors::ControllerCaller
|
27
|
-
|
28
|
-
web.build!
|
47
|
+
|
48
|
+
web.build!
|
29
49
|
end
|
30
50
|
|
31
51
|
|
32
52
|
#
|
33
|
-
#
|
53
|
+
# RackAdapter
|
34
54
|
#
|
35
|
-
rad.http.stack.push(-> builder {
|
55
|
+
rad.http.stack.push(-> builder {
|
36
56
|
# CommonLogger, ShowExceptions, Lint
|
37
57
|
builder.use Rack::Lint if rad.development?
|
38
|
-
# builder.use Rad::Middleware::StaticFiles if rad.http.static? and rad.http.public_path? and rad.development?
|
39
58
|
|
40
|
-
#
|
59
|
+
# Static Files
|
60
|
+
if rad.http.static? and rad.http.public_path and rad.development?
|
61
|
+
filters = /^\/.*?\/static\/|^\/static\/|\/favicon/
|
62
|
+
builder.use Rad::Assets::StaticFiles, filters
|
63
|
+
end
|
64
|
+
|
65
|
+
# use Rack::Session::Cookie, key: 'rack.session', domain: 'foo.com', path: '/', expire_after: 2592000, secret: 'change_me'
|
41
66
|
builder.use Rack::Session::Cookie, rad.http.session.stringify_keys if rad.http.session
|
42
|
-
|
67
|
+
|
43
68
|
# builder.use Rack::CommonLogger
|
44
69
|
builder.use Rack::MethodOverride
|
45
70
|
})
|
data/lib/rad/router/_router.rb
CHANGED
@@ -72,7 +72,7 @@ class Rad::Router
|
|
72
72
|
|
73
73
|
raise "invalid route! No method '#{method}' for #{klass}!" unless klass.instance_methods.include? method
|
74
74
|
raise "invalid route! You try to call protected method '#{method}' for '#{path}'!" unless klass.public_instance_methods.include? method
|
75
|
-
|
75
|
+
|
76
76
|
return klass, method, params
|
77
77
|
end
|
78
78
|
|
File without changes
|
@@ -44,8 +44,8 @@ rspec do
|
|
44
44
|
before{set_controller controller_class}
|
45
45
|
end
|
46
46
|
|
47
|
-
def wcall *args, &block
|
48
|
-
workspace_variables, params = parse_wcall_arguments *args
|
47
|
+
def wcall *args, &block
|
48
|
+
workspace_variables, params = parse_wcall_arguments *args
|
49
49
|
ccall nil, nil, params, workspace_variables, &block
|
50
50
|
end
|
51
51
|
|
@@ -64,14 +64,18 @@ rspec do
|
|
64
64
|
|
65
65
|
workspace_variables = {}
|
66
66
|
if args.size == 1 and first.is_a?(String) and first =~ /^\/|^http:/
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
67
|
+
uri = Uri.parse first
|
68
|
+
workspace_variables[:path] = uri.path
|
69
|
+
workspace_variables[:params] = uri.query_values
|
70
|
+
workspace_variables[:env] = Rad::Http::Request.stub_environment(first)
|
71
|
+
# if first =~ /^\//
|
72
|
+
# workspace_variables[:path] = first
|
73
|
+
# else
|
74
|
+
# uri = Uri.parse first
|
75
|
+
# workspace_variables[:path] = uri.path
|
76
|
+
# workspace_variables[:params] = uri.query_values
|
77
|
+
# workspace_variables[:env] = Rad::Http::Request.stub_environment(first)
|
78
|
+
# end
|
75
79
|
elsif (first.is_a?(String) or first.is_a?(Symbol)) and args.size <= 2
|
76
80
|
workspace_variables[:path] = '/'
|
77
81
|
workspace_variables[:class] = wcall_options[:controller] || raise("not defined wcall controller (use set_wcall controller: SomeController)!")
|
@@ -88,7 +92,7 @@ rspec do
|
|
88
92
|
|
89
93
|
# preparing environment
|
90
94
|
workspace_variables[:env] ||= {}
|
91
|
-
workspace_variables[:env].reverse_merge!
|
95
|
+
workspace_variables[:env].reverse_merge! Rad::Http::Request.stub_environment
|
92
96
|
|
93
97
|
# setting request method
|
94
98
|
if request_method = params.delete(:_method) || params.delete('_method')
|
data/lib/rad/spec/web.rb
ADDED
data/lib/rad/spec.rb
CHANGED
data/lib/rad/tasks.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rake_ext'
|
2
|
+
require 'ruby_ext'
|
3
|
+
|
4
|
+
task :environment do
|
5
|
+
require 'rad'
|
6
|
+
rad.mode = ENV['m'] || ENV['mode'] || ENV['env'] || ENV['environment'] || :development
|
7
|
+
|
8
|
+
require 'rad/cli/helper'
|
9
|
+
Rad::Cli::Helper.use_runtime_path!
|
10
|
+
|
11
|
+
rad.runtime_path = File.expand_path '.'
|
12
|
+
|
13
|
+
load "./init.rb"
|
14
|
+
rad.environment
|
15
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Sets format for :js as :html and wraps body into <textarea>
|
2
|
+
# Forms with files can be submitted by ajax only via iframe, and it requires
|
3
|
+
# the response have 'html' encoding and be wrapped into <textarea>
|
4
|
+
class Rad::Web::Processors::AjaxHelper < Rad::Conveyors::Processor
|
5
|
+
def call
|
6
|
+
response = workspace.response.must_be.defined
|
7
|
+
request = workspace.request.must_be.defined
|
8
|
+
|
9
|
+
next_processor.call
|
10
|
+
|
11
|
+
if workspace.params? and workspace.params.format == 'js' and !request.xhr?
|
12
|
+
response.content_type = Mime['html']
|
13
|
+
workspace.content = "<textarea>#{workspace.content}</textarea>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/rad/{core_web/_controller_micelaneous_helper.rb → web/_controller_miscellaneous_helper.rb}
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
module Rad::
|
1
|
+
module Rad::ControllerMiscellaneousHelper
|
2
2
|
def reload_page
|
3
3
|
params = workspace.params
|
4
4
|
params.format.must_be.in 'html', 'js'
|
@@ -11,7 +11,7 @@ module Rad::ControllerMicelaneousHelper
|
|
11
11
|
)
|
12
12
|
throw :halt, "window.location.reload();"
|
13
13
|
else
|
14
|
-
redirect_to
|
14
|
+
redirect_to request.env["HTTP_REFERER"]
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# enshure domain has no www. except if there's custom subdomain
|
2
|
+
class Rad::Web::Processors::EnsureNoWww < Rad::Conveyors::Processor
|
3
|
+
def call
|
4
|
+
workspace.params.must_be.defined
|
5
|
+
if workspace.params.format == 'html' and url_with_www?
|
6
|
+
redirect_without_www
|
7
|
+
else
|
8
|
+
next_processor.call
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
def uri
|
14
|
+
@uri ||= Uri.parse workspace.request.url
|
15
|
+
end
|
16
|
+
|
17
|
+
def url_with_www?
|
18
|
+
uri.host =~ /^www\./
|
19
|
+
end
|
20
|
+
|
21
|
+
def redirect_without_www
|
22
|
+
uri.host = uri.host.sub(/^www\./, '')
|
23
|
+
url = uri.to_s
|
24
|
+
|
25
|
+
response = workspace.response
|
26
|
+
response.status = 301
|
27
|
+
response.headers['Location'] = url
|
28
|
+
response.body = %(<html><body>You are being <a href="#{url.html_escape}">redirected</a>.</body></html>)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#
|
2
|
+
# Processor
|
3
|
+
#
|
4
|
+
class Rad::Web::Processors::PrepareAutenticityToken < Rad::Conveyors::Processor
|
5
|
+
def call
|
6
|
+
if rad.http.session
|
7
|
+
request = workspace.request.must_be.defined
|
8
|
+
params = workspace.params.must_be.defined
|
9
|
+
|
10
|
+
token = request.session['authenticity_token']
|
11
|
+
|
12
|
+
if token.blank? and request.get?
|
13
|
+
token = generate_authenticity_token
|
14
|
+
request.session['authenticity_token'] = token
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
next_processor.call
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
protected
|
23
|
+
def generate_authenticity_token
|
24
|
+
ActiveSupport::SecureRandom.base64(32)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
#
|
30
|
+
# Controller
|
31
|
+
#
|
32
|
+
module Rad::Controller::ForgeryProtector
|
33
|
+
attr_reader :authenticity_token
|
34
|
+
protected
|
35
|
+
def protect_from_forgery
|
36
|
+
if request.session
|
37
|
+
sat = request.session['authenticity_token']
|
38
|
+
|
39
|
+
raise "invalid authenticity token!" unless \
|
40
|
+
request.get? or
|
41
|
+
!request.from_browser? or
|
42
|
+
(sat.present? and sat == params.authenticity_token)
|
43
|
+
|
44
|
+
@authenticity_token = sat
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Rad::Controller::Http.include Rad::Controller::ForgeryProtector
|
50
|
+
|
51
|
+
Rad::Controller::Http::ClassMethods.class_eval do
|
52
|
+
def protect_from_forgery options = {}
|
53
|
+
before :protect_from_forgery, options
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
#
|
59
|
+
# View
|
60
|
+
#
|
61
|
+
Rad::Html::FormHelper.class_eval do
|
62
|
+
attr_reader :authenticity_token
|
63
|
+
|
64
|
+
alias_method :form_tag_without_at, :form_tag
|
65
|
+
def form_tag *args, &b
|
66
|
+
form_tag_without_at *args do
|
67
|
+
concat(hidden_field_tag('authenticity_token', authenticity_token) + "\n") if authenticity_token
|
68
|
+
b.call if b
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,10 +1,19 @@
|
|
1
|
+
module Rad::Web
|
2
|
+
module Processors
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
1
6
|
%w(
|
2
|
-
|
7
|
+
_controller_miscellaneous_helper
|
3
8
|
|
4
9
|
_router/abstract_routing_helper
|
5
10
|
_router/view_routing_helper
|
6
|
-
_router/controller_routing_helper
|
7
|
-
|
11
|
+
_router/controller_routing_helper
|
12
|
+
|
13
|
+
_ajax_helper
|
14
|
+
_ensure_no_www
|
15
|
+
_protect_from_forgery
|
16
|
+
).each{|f| require "rad/web/#{f}"}
|
8
17
|
|
9
18
|
|
10
19
|
# View helpers
|
@@ -19,7 +28,7 @@ end
|
|
19
28
|
[
|
20
29
|
Rad::Html::FlashHelper,
|
21
30
|
Rad::Router::CoreRoutingHelper, Rad::ControllerRoutingHelper,
|
22
|
-
Rad::
|
31
|
+
Rad::ControllerMiscellaneousHelper
|
23
32
|
].each do |helper|
|
24
33
|
Rad::Controller::Abstract.inherit helper
|
25
34
|
end
|
File without changes
|
File without changes
|
File without changes
|
data/lib/rad.rb
CHANGED
data/readme.md
CHANGED
@@ -1,20 +1,27 @@
|
|
1
1
|
# Rad - Ruby Web Framework
|
2
2
|
|
3
|
-
|
3
|
+
Simple and highly customizable Web Framework encouraging to build an app as a set of low-coupled components instead of monolith.
|
4
|
+
With an architecture heavily inspired by Rails, Spring IoC, JBoss Seam and JEE (but without config burden).
|
4
5
|
|
5
|
-
You can start
|
6
|
+
You can start instantly using one of predefined profiles, or take a total control over all aspects of environment and completelly modify it according to Your goals (everything is a component, if You don't like the router, controller or views - throw it out and introduce Your own).
|
6
7
|
|
7
|
-
|
8
|
+
Usually, the first thing You want to now about some unknown framework: "where's the demo?" and "where's the sample?".
|
8
9
|
|
9
|
-
|
10
|
+
Here's some **sites built with Rad**:
|
11
|
+
|
12
|
+
[![](https://github.com/alexeypetrushin/rad_core/raw/master/docs/robotigra.thumb.png)](http://robotigra.ru) [![](https://github.com/alexeypetrushin/rad_core/raw/master/docs/petrushin.thumb.png)](http://petrush.in) [![](https://github.com/alexeypetrushin/rad_core/raw/master/docs/rubylang.thumb.png)](http://ruby-lang.info)
|
13
|
+
|
14
|
+
Here's the classic **sample blog app** [rad-sample.heroku.com](http://rad-sample.heroku.com) (it's hosted using free Heroku instance and sometimes it takes about 10sec to start up, so please be patient) sources [github.com/alexeypetrushin/rad_sample](http://github.com/alexeypetrushin/rad_sample)
|
15
|
+
|
16
|
+
## Goals behind this framework:
|
10
17
|
|
11
18
|
- Divide and rule (build app as a set of cooperated components)
|
12
|
-
- True support for OOP (models, routes,
|
19
|
+
- True support for OOP (models, controllers, polymorphic routes, plymorphic views)
|
13
20
|
- Simple things should be simple (simple API, instant start with minimal config)
|
14
21
|
- Complete control if You need it, it's designed to be open and customizable
|
15
22
|
- Agile/Extreme development should be easy (specs, iterative development, fast prototyping)
|
16
23
|
|
17
|
-
## Some thecnical thoughts and ideas
|
24
|
+
## Some thecnical thoughts and ideas:
|
18
25
|
|
19
26
|
- I tried to keep codebase as small and simple as possible and delegate job do another libraries, so actually it's an integration layer on top of other libraries that focuses on providing nice and consistent interface.
|
20
27
|
- It uses "conveyors" for assembling all kind of responces, and it's very easy to set custom assembly chain or modify existing one. This way You have a strong controll over wide aspects of framework.
|
@@ -58,4 +65,4 @@ With Rad I tried to save all the goodness and use API as closed to Rails as poss
|
|
58
65
|
|
59
66
|
## License
|
60
67
|
|
61
|
-
Copyright (c) Alexey Petrushin http://
|
68
|
+
Copyright (c) Alexey Petrushin http://petrush.in, released under the **MIT** license.
|
@@ -25,14 +25,14 @@ describe "Abstract" do
|
|
25
25
|
ccall WorkspaceVariablesSpec, :action
|
26
26
|
|
27
27
|
workspace.controller.should be_a(WorkspaceVariablesSpec)
|
28
|
-
|
28
|
+
response.should respond_to("body=")
|
29
29
|
|
30
30
|
expected_result = {
|
31
31
|
params: {},
|
32
32
|
|
33
33
|
class: WorkspaceVariablesSpec,
|
34
34
|
method_name: :action,
|
35
|
-
|
35
|
+
action_name: :action
|
36
36
|
}
|
37
37
|
workspace.to_h(true).subset(expected_result.keys).should == expected_result
|
38
38
|
end
|
@@ -55,7 +55,7 @@ describe "Error handling" do
|
|
55
55
|
end
|
56
56
|
|
57
57
|
it "should catch errors with redirect (from error)" do
|
58
|
-
# if response.headers['Location'] has been set before redirect, it'll do redirect
|
58
|
+
# error: if response.headers['Location'] has been set before redirect, it'll do redirect
|
59
59
|
# after error will be catched and no error message will be displayed
|
60
60
|
|
61
61
|
class ::ErrorInRedirectSpec
|