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.
Files changed (72) hide show
  1. data/Rakefile +3 -1
  2. data/bin/rad +33 -0
  3. data/lib/components/configurators.rb +5 -0
  4. data/lib/components/environment.production.yml +1 -0
  5. data/lib/components/environment.yml +30 -1
  6. data/lib/components/http.yml +12 -1
  7. data/lib/components/web.rb +2 -2
  8. data/lib/rad/_support/active_support/{micelaneous.rb → miscellaneous.rb} +0 -0
  9. data/lib/rad/_support/active_support.rb +1 -1
  10. data/lib/rad/_support/exception.rb +9 -40
  11. data/lib/rad/_support/string.rb +7 -1
  12. data/lib/rad/cli/helper.rb +34 -0
  13. data/lib/rad/configurators/_require.rb +13 -0
  14. data/lib/rad/configurators/abstract.rb +24 -0
  15. data/lib/rad/configurators/runtime.rb +4 -0
  16. data/lib/rad/configurators/web.rb +34 -0
  17. data/lib/rad/controller/_abstract/{micelaneous.rb → miscellaneous.rb} +1 -1
  18. data/lib/rad/controller/_abstract/render.rb +54 -53
  19. data/lib/rad/controller/_abstract.rb +16 -8
  20. data/lib/rad/controller/_context.rb +3 -9
  21. data/lib/rad/controller/_http.rb +22 -17
  22. data/lib/rad/controller/_require.rb +1 -1
  23. data/lib/rad/controller/processors/controller_caller.rb +5 -13
  24. data/lib/rad/controller/processors/controller_error_handling.rb +2 -2
  25. data/lib/rad/environment/_environment.rb +4 -0
  26. data/lib/rad/environment/_logger.rb +5 -5
  27. data/lib/rad/html/_require.rb +1 -1
  28. data/lib/rad/http/_http.rb +8 -4
  29. data/lib/rad/http/_http_adapter.rb +1 -21
  30. data/lib/rad/http/_request.rb +48 -7
  31. data/lib/rad/http/_require.rb +1 -1
  32. data/lib/rad/http/_response.rb +1 -1
  33. data/lib/rad/http/_support/rack/fixes.rb +6 -0
  34. data/lib/rad/http/processors/prepare_params.rb +1 -1
  35. data/lib/rad/mailer/processors/letter_builder.rb +3 -9
  36. data/lib/rad/profiles/web.rb +35 -10
  37. data/lib/rad/router/_router.rb +1 -1
  38. data/lib/rad/router/{micelaneous_router.rb → miscellaneous_router.rb} +0 -0
  39. data/lib/rad/spec/http_controller.rb +15 -11
  40. data/lib/rad/spec/web.rb +7 -0
  41. data/lib/rad/spec.rb +1 -0
  42. data/lib/rad/tasks.rb +15 -0
  43. data/lib/rad/template/_context.rb +0 -4
  44. data/lib/rad/template/_template.rb +1 -1
  45. data/lib/rad/web/_ajax_helper.rb +16 -0
  46. data/lib/rad/{core_web/_controller_micelaneous_helper.rb → web/_controller_miscellaneous_helper.rb} +2 -2
  47. data/lib/rad/web/_ensure_no_www.rb +30 -0
  48. data/lib/rad/web/_protect_from_forgery.rb +71 -0
  49. data/lib/rad/{core_web → web}/_require.rb +13 -4
  50. data/lib/rad/{core_web → web}/_router/abstract_routing_helper.rb +0 -0
  51. data/lib/rad/{core_web → web}/_router/controller_routing_helper.rb +0 -0
  52. data/lib/rad/{core_web → web}/_router/view_routing_helper.rb +0 -0
  53. data/lib/rad.rb +1 -1
  54. data/readme.md +14 -7
  55. data/spec/controller/abstract_spec.rb +2 -2
  56. data/spec/controller/error_handling_spec.rb +1 -1
  57. data/spec/controller/http_spec/views/ViewVariablesSpec/action.erb +2 -0
  58. data/spec/controller/http_spec.rb +18 -1
  59. data/spec/controller/render_spec.rb +13 -13
  60. data/spec/http/http_spec.rb +1 -1
  61. data/spec/http/{micelaneous_spec.rb → miscellaneous_spec.rb} +0 -0
  62. data/spec/router/integration_spec.rb +4 -1
  63. data/spec/router/object_router_spec.rb +1 -1
  64. data/spec/router/persistent_params_spec.rb +1 -1
  65. data/spec/router/restful_router_spec.rb +1 -1
  66. data/spec/web/basic_spec.rb +8 -4
  67. data/spec/web/controller_routing_helper_spec.rb +4 -3
  68. data/spec/web/flash_spec.rb +2 -3
  69. data/spec/web/protect_from_forgery_spec.rb +187 -0
  70. data/spec/web/spec_helper_spec.rb +9 -5
  71. data/spec/web/view_routing_helper_spec.rb +1 -1
  72. metadata +27 -12
@@ -1,6 +1,6 @@
1
1
  class Rad::Html
2
2
  attr_accessor :remote_link_formats
3
- require_attr :remote_link_formats
3
+ attr_required :remote_link_formats
4
4
  end
5
5
 
6
6
  %w(
@@ -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, :mock_environment, to: :http_adapter
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
@@ -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
- # subdomains = request.subdomains.select{|n| n != 'www'}
40
- # subdomain = subdomains.last
41
- # pure_domain = request.domain.sub(/\A#{subdomains.join(".")}\./, "")
42
- #
43
- # domain = subdomain.blank? ? pure_domain : "#{subdomain}.#{pure_domain}"
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
@@ -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
- require_attr :host, :port, :url_root, :default_format
9
+ attr_required :host, :port, :url_root, :default_format
10
10
  def static?; !!@static end
11
11
 
12
12
  attr_writer :public_path
@@ -47,7 +47,7 @@ class Rad::Http::Response < Rack::Response
47
47
 
48
48
  def clear
49
49
  @status = 200
50
- @header = Rack::Utils::HeaderHash.new("Content-Type" => nil)
50
+ @header = Rack::Utils::HeaderHash.new("Content-Type" => nil)
51
51
  @length = 0
52
52
  @body = []
53
53
  end
@@ -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
- action = workspace.action = workspace.method_name
8
+ action_name = workspace.action_name = workspace.method_name
9
9
 
10
10
  # call
11
- content = catch :halt do
12
- controller.run_callbacks :action, method: action do
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
 
@@ -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
- # Rack
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
- # use Rack::Session::Cookie, key: 'rack.session', domain: 'foo.com', path: '/', expire_after: 2592000, secret: 'change_me'
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
  })
@@ -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
 
@@ -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
- if first =~ /^\//
68
- workspace_variables[:path] = first
69
- else
70
- uri = Uri.parse first
71
- workspace_variables[:path] = uri.path
72
- workspace_variables[:params] = uri.query_values
73
- workspace_variables[:env] = rad.http.mock_environment(first)
74
- end
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! rad.http.mock_environment
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')
@@ -0,0 +1,7 @@
1
+ require 'rad/web/_require'
2
+
3
+ Rad::Controller::Http::ClassMethods.class_eval do
4
+ # Rad::Controller::ForgeryProtector.class_eval do
5
+ alias_method :protect_from_forgery_without_test, :protect_from_forgery
6
+ def protect_from_forgery; end
7
+ end
data/lib/rad/spec.rb CHANGED
@@ -10,4 +10,5 @@ require 'rad'
10
10
  remote
11
11
  mailer
12
12
  router
13
+ web
13
14
  ).each{|f| require "rad/spec/#{f}"}
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
@@ -63,10 +63,6 @@ class Rad::Template::Context
63
63
  end
64
64
  def has_content_for? name
65
65
  content_variables.include? name.to_s
66
- end
67
-
68
- def params
69
- workspace.params
70
66
  end
71
67
 
72
68
  def find_relative_template *args
@@ -2,7 +2,7 @@ class Rad::Template
2
2
  inject logger: :logger, environment: :environment
3
3
 
4
4
  attr_accessor :relative_path_resolver, :prefixes
5
- require_attr :prefixes
5
+ attr_required :prefixes
6
6
 
7
7
  def initialize
8
8
  @relative_path_resolver = RelativePathResolver.new
@@ -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
@@ -1,4 +1,4 @@
1
- module Rad::ControllerMicelaneousHelper
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 workspace.request.env["HTTP_REFERER"]
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
- _controller_micelaneous_helper
7
+ _controller_miscellaneous_helper
3
8
 
4
9
  _router/abstract_routing_helper
5
10
  _router/view_routing_helper
6
- _router/controller_routing_helper
7
- ).each{|f| require "rad/core_web/#{f}"}
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::ControllerMicelaneousHelper
31
+ Rad::ControllerMiscellaneousHelper
23
32
  ].each do |helper|
24
33
  Rad::Controller::Abstract.inherit helper
25
34
  end
data/lib/rad.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Rad
2
- VERSION = '0.0.1'
2
+ VERSION = '0.2.1'
3
3
  end
4
4
 
5
5
  require 'rad/_support/require'
data/readme.md CHANGED
@@ -1,20 +1,27 @@
1
1
  # Rad - Ruby Web Framework
2
2
 
3
- Goals: **give You tools to fight complexity** and freedom to do it in a way You like.
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 quickly using one of predefined *opinionated* profiles, or take a total control over all aspects of environment and completelly modify it according to Your goals.
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
- If You whould like **to see it working, please go to http://ruby-lang.info** - that site powered by Rad.
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
- It's designed to:
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, controllers/resources + views)
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://4ire.net, released under the **MIT** license.
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
- workspace.response.should respond_to("body=")
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
- action: :action
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
@@ -0,0 +1,2 @@
1
+ request: <%= !!request %>
2
+ response: <%= !!response %>