padrino-core 0.10.7 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/lib/padrino-core.rb +58 -4
  3. data/lib/padrino-core/application.rb +38 -16
  4. data/lib/padrino-core/application/flash.rb +229 -0
  5. data/lib/padrino-core/application/rendering.rb +39 -11
  6. data/lib/padrino-core/application/rendering/extensions/erubis.rb +55 -0
  7. data/lib/padrino-core/application/rendering/extensions/haml.rb +26 -0
  8. data/lib/padrino-core/application/rendering/extensions/slim.rb +14 -0
  9. data/lib/padrino-core/application/routing.rb +106 -35
  10. data/lib/padrino-core/cli/base.rb +41 -38
  11. data/lib/padrino-core/cli/rake.rb +30 -9
  12. data/lib/padrino-core/cli/rake_tasks.rb +9 -14
  13. data/lib/padrino-core/loader.rb +23 -9
  14. data/lib/padrino-core/locale/fr.yml +1 -1
  15. data/lib/padrino-core/locale/ru.yml +1 -1
  16. data/lib/padrino-core/logger.rb +48 -32
  17. data/lib/padrino-core/module.rb +58 -0
  18. data/lib/padrino-core/mounter.rb +15 -5
  19. data/lib/padrino-core/reloader.rb +14 -12
  20. data/lib/padrino-core/server.rb +4 -4
  21. data/lib/padrino-core/support_lite.rb +43 -6
  22. data/lib/padrino-core/version.rb +1 -1
  23. data/padrino-core.gemspec +9 -4
  24. data/test/fixtures/app_gem/Gemfile +4 -0
  25. data/test/fixtures/app_gem/app/app.rb +3 -0
  26. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  27. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  28. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  29. data/test/mini_shoulda.rb +1 -1
  30. data/test/test_application.rb +38 -21
  31. data/test/test_csrf_protection.rb +80 -0
  32. data/test/test_filters.rb +70 -0
  33. data/test/test_flash.rb +168 -0
  34. data/test/test_logger.rb +27 -0
  35. data/test/test_mounter.rb +24 -2
  36. data/test/test_reloader_simple.rb +4 -4
  37. data/test/test_rendering.rb +75 -4
  38. data/test/test_routing.rb +164 -35
  39. data/test/test_support_lite.rb +56 -0
  40. metadata +52 -29
@@ -0,0 +1,55 @@
1
+ begin
2
+ require 'erubis'
3
+
4
+ module Padrino
5
+ module Erubis
6
+ ##
7
+ # SafeBufferEnhancer is an Erubis Enhancer that compiles templates that
8
+ # are fit for using ActiveSupport::SafeBuffer as a Buffer.
9
+ #
10
+ # @api private
11
+ module SafeBufferEnhancer
12
+ def add_expr_literal(src, code)
13
+ src << " #{@bufvar}.concat((" << code << ').to_s);'
14
+ end
15
+
16
+ def add_expr_escaped(src, code)
17
+ src << " #{@bufvar}.safe_concat " << code << ';'
18
+ end
19
+
20
+ def add_text(src, text)
21
+ src << " #{@bufvar}.safe_concat '" << escape_text(text) << "';" unless text.empty?
22
+ end
23
+ end
24
+
25
+ ##
26
+ # SafeBufferTemplate is the classic Erubis template, augmented with
27
+ # SafeBufferEnhancer.
28
+ #
29
+ # @api private
30
+ class SafeBufferTemplate < ::Erubis::Eruby
31
+ include SafeBufferEnhancer
32
+ end
33
+
34
+ ##
35
+ # Modded ErubisTemplate that doesn't insist in an String as output
36
+ # buffer.
37
+ #
38
+ # @api private
39
+ class Template < Tilt::ErubisTemplate
40
+ def precompiled_preamble(locals)
41
+ old_postamble = super.split("\n")[0..-2]
42
+ [old_postamble, "#{@outvar} = _buf = (#{@outvar} || ActiveSupport::SafeBuffer.new)"].join("\n")
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ Tilt.prefer Padrino::Erubis::Template, :erb
49
+
50
+ if defined? Padrino::Rendering
51
+ Padrino::Rendering.engine_configurations[:erb] =
52
+ {:engine_class => Padrino::Erubis::SafeBufferTemplate}
53
+ end
54
+ rescue LoadError
55
+ end
@@ -0,0 +1,26 @@
1
+ begin
2
+ require 'haml'
3
+ require 'haml/helpers/xss_mods'
4
+
5
+ module Haml
6
+ module Helpers
7
+ include XssMods
8
+ end
9
+
10
+ module Util
11
+ def self.rails_xss_safe?
12
+ true
13
+ end
14
+ end
15
+ end
16
+
17
+ if defined? Padrino::Rendering
18
+ Padrino::Rendering.engine_configurations[:haml] =
19
+ {:escape_html => true}
20
+
21
+ class Tilt::HamlTemplate
22
+ include Padrino::Rendering::SafeTemplate
23
+ end
24
+ end
25
+ rescue LoadError
26
+ end
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'slim'
3
+
4
+ if defined? Padrino::Rendering
5
+ Padrino::Rendering.engine_configurations[:slim] =
6
+ {:generator => Temple::Generators::RailsOutputBuffer,
7
+ :buffer => "@_out_buf", :use_html_safe => true}
8
+
9
+ class Slim::Template
10
+ include Padrino::Rendering::SafeTemplate
11
+ end
12
+ end
13
+ rescue LoadError
14
+ end
@@ -11,6 +11,9 @@ class Sinatra::Request
11
11
  def controller
12
12
  route_obj && route_obj.controller
13
13
  end
14
+ def action
15
+ route_obj && route_obj.action
16
+ end
14
17
  end
15
18
 
16
19
  ##
@@ -28,8 +31,8 @@ class HttpRouter
28
31
  @route = path.route
29
32
  @params ||= {}
30
33
  @params.update(env['router.params'])
31
- @block_params = if path.route.is_a?(HttpRouter::RegexRoute)
32
- params_list = env['router.request'].extra_env['router.regex_match'].to_a
34
+ @block_params = if match_data = env['router.request'].extra_env['router.regex_match']
35
+ params_list = match_data.to_a
33
36
  params_list.shift
34
37
  @params[:captures] = params_list
35
38
  params_list
@@ -47,7 +50,6 @@ class HttpRouter
47
50
  (@route.before_filters - settings.filters[:before]).each { |block| instance_eval(&block) }
48
51
  @layout = path.route.use_layout if path.route.use_layout
49
52
  @route.custom_conditions.each { |block| pass if block.bind(self).call == false } if @route.custom_conditions
50
- @block_params = @block_params[0, @route.dest.arity] if @route.dest.arity > 0
51
53
  halt_response = catch(:halt) { route_eval { @route.dest[self, @block_params] } }
52
54
  @_response_buffer = halt_response.is_a?(Array) ? halt_response.last : halt_response
53
55
  successful = true
@@ -62,7 +64,7 @@ class HttpRouter
62
64
 
63
65
  # @private
64
66
  class Route
65
- attr_accessor :use_layout, :controller, :cache, :cache_key, :cache_expires_in
67
+ attr_accessor :use_layout, :controller, :action, :cache, :cache_key, :cache_expires_in, :parent
66
68
 
67
69
  def before_filters(&block)
68
70
  @_before_filters ||= []
@@ -84,6 +86,40 @@ class HttpRouter
84
86
 
85
87
  @_custom_conditions
86
88
  end
89
+
90
+ def significant_variable_names
91
+ @significant_variable_names ||= @original_path.nil? ? [] : @original_path.scan(/(^|[^\\])[:\*]([a-zA-Z0-9_]+)/).map{|p| p.last.to_sym}
92
+ end
93
+ end
94
+
95
+ class Node::Path
96
+ def to_code
97
+ path_ivar = inject_root_ivar(self)
98
+ "#{"if !callback && request.path.size == 1 && request.path.first == '' && (request.rack_request.head? || request.rack_request.get?) && request.rack_request.path_info[-1] == ?/
99
+ catch(:pass) do
100
+ response = ::Rack::Response.new
101
+ response.redirect(request.rack_request.path_info[0, request.rack_request.path_info.size - 1], 302)
102
+ return response.finish
103
+ end
104
+ end" if router.redirect_trailing_slash?}
105
+
106
+ #{"if request.#{router.ignore_trailing_slash? ? 'path_finished?' : 'path.empty?'}" unless route.match_partially}
107
+ catch(:pass) do
108
+ if callback
109
+ request.called = true
110
+ callback.call(Response.new(request, #{path_ivar}))
111
+ else
112
+ env = request.rack_request.dup.env
113
+ env['router.request'] = request
114
+ env['router.params'] ||= {}
115
+ #{"env['router.params'].merge!(Hash[#{param_names.inspect}.zip(request.params)])" if dynamic?}
116
+ @router.rewrite#{"_partial" if route.match_partially}_path_info(env, request)
117
+ response = @router.process_destination_path(#{path_ivar}, env)
118
+ return response unless router.pass_on_response(response)
119
+ end
120
+ end
121
+ #{"end" unless route.match_partially}"
122
+ end
87
123
  end
88
124
  end
89
125
 
@@ -98,7 +134,7 @@ module Padrino
98
134
  def apply?(request)
99
135
  detect = @args.any? do |arg|
100
136
  case arg
101
- when Symbol then request.route_obj && (request.route_obj.named == arg or request.route_obj.named == [@scoped_controller, arg].flatten.join("_").to_sym)
137
+ when Symbol then request.route_obj && (request.route_obj.name == arg or request.route_obj.name == [@scoped_controller, arg].flatten.join("_").to_sym)
102
138
  else arg === request.path_info
103
139
  end
104
140
  end || @options.any? do |name, val|
@@ -166,7 +202,7 @@ module Padrino
166
202
  # Class methods responsible for enhanced routing for controllers.
167
203
  module ClassMethods
168
204
  ##
169
- # Method for organize in a better way our routes.
205
+ # Method to organize our routes in a better way.
170
206
  #
171
207
  # @param [Array] args
172
208
  # Controller arguments.
@@ -237,8 +273,8 @@ module Padrino
237
273
  # get :index, :map => "/:lang" do; "params[:lang] == :de"; end
238
274
  # end
239
275
  #
240
- # In a controller before and after filters are scoped and didn't affect other controllers or main app.
241
- # In a controller layout are scoped and didn't affect others controllers and main app.
276
+ # In a controller, before and after filters are scoped and don't affect other controllers or the main app.
277
+ # In a controller, layouts are scoped and don't affect other controllers or the main app.
242
278
  #
243
279
  # @example
244
280
  # controller :posts do
@@ -449,7 +485,8 @@ module Padrino
449
485
  #
450
486
  def recognize_path(path)
451
487
  responses = @router.recognize(Rack::MockRequest.env_for(path))
452
- [responses[0].path.route.named, responses[0].params]
488
+ responses = responses[0] if responses[0].is_a?(Array)
489
+ [responses[0].path.route.name, responses[0].params]
453
490
  end
454
491
 
455
492
  ##
@@ -470,11 +507,12 @@ module Padrino
470
507
  params[:format] = params[:format].to_s unless params[:format].nil?
471
508
  params = value_to_param(params)
472
509
  end
473
- url = if params_array.empty?
474
- compiled_router.url(name, params)
475
- else
476
- compiled_router.url(name, *(params_array << params))
477
- end
510
+ url =
511
+ if params_array.empty?
512
+ compiled_router.path(name, params)
513
+ else
514
+ compiled_router.path(name, *(params_array << params))
515
+ end
478
516
  url[0,0] = conform_uri(uri_root) if defined?(uri_root)
479
517
  url[0,0] = conform_uri(ENV['RACK_BASE_URI']) if ENV['RACK_BASE_URI']
480
518
  url = "/" if url.blank?
@@ -556,8 +594,17 @@ module Padrino
556
594
  # Do padrino parsing. We dup options so we can build HEAD request correctly
557
595
  route_options = options.dup
558
596
  route_options[:provides] = @_provides if @_provides
597
+
598
+ # CSRF protection is always active except when explicitly switched off
599
+ if allow_disabled_csrf
600
+ unless route_options[:csrf_protection] == false
601
+ route_options[:csrf_protection] = true
602
+ end
603
+ end
604
+
559
605
  path, *route_options[:with] = path if path.is_a?(Array)
560
- path, name, options, route_options = *parse_route(path, route_options, verb)
606
+ action = path
607
+ path, name, route_parents, options, route_options = *parse_route(path, route_options, verb)
561
608
  options.reverse_merge!(@_conditions) if @_conditions
562
609
 
563
610
  # Sinatra defaults
@@ -572,20 +619,22 @@ module Padrino
572
619
 
573
620
  # HTTPRouter route construction
574
621
  route = router.add(path, route_options)
575
- route.name(name) if name
622
+ route.name = name if name
623
+ route.action = action
576
624
  priority_name = options.delete(:priority) || :normal
577
625
  priority = ROUTE_PRIORITY[priority_name] or raise("Priority #{priority_name} not recognized, try #{ROUTE_PRIORITY.keys.join(', ')}")
578
626
  route.cache = options.key?(:cache) ? options.delete(:cache) : @_cache
579
- route.send(verb.downcase.to_sym)
580
- route.host(options.delete(:host)) if options.key?(:host)
581
- route.user_agent(options.delete(:agent)) if options.key?(:agent)
627
+ route.parent = route_parents ? (route_parents.count == 1 ? route_parents.first : route_parents) : route_parents
628
+ route.add_request_method(verb.downcase.to_sym)
629
+ route.host = options.delete(:host) if options.key?(:host)
630
+ route.user_agent = options.delete(:agent) if options.key?(:agent)
582
631
  if options.key?(:default_values)
583
632
  defaults = options.delete(:default_values)
584
- route.default(defaults) if defaults
633
+ route.add_default_values(defaults) if defaults
585
634
  end
586
635
  options.delete_if do |option, args|
587
- if route.send(:significant_variable_names).include?(option)
588
- route.matching(option => Array(args).first)
636
+ if route.significant_variable_names.include?(option)
637
+ route.add_match_with(option => Array(args).first)
589
638
  true
590
639
  end
591
640
  end
@@ -646,8 +695,8 @@ module Padrino
646
695
 
647
696
  if @_use_format or format_params = options[:provides]
648
697
  process_path_for_provides(path, format_params)
649
- options[:matching] ||= {}
650
- options[:matching][:format] = /[^\.]+/
698
+ # options[:add_match_with] ||= {}
699
+ # options[:add_match_with][:format] = /[^\.]+/
651
700
  end
652
701
 
653
702
  absolute_map = map && map[0] == ?/
@@ -657,14 +706,14 @@ module Padrino
657
706
  if map.blank? and !absolute_map
658
707
  controller_path = controller.join("/")
659
708
  path.gsub!(%r{^\(/\)|/\?}, "")
660
- path = File.join(controller_path, path)
709
+ path = File.join(controller_path, path) unless @_map
661
710
  end
662
711
  # Here we build the correct name route
663
712
  end
664
713
 
665
714
  # Now we need to parse our 'parent' params and parent scope
666
715
  if !absolute_map and parent_params = options.delete(:parent) || @_parents
667
- parent_params = Array(@_parents) + Array(parent_params)
716
+ parent_params = (Array(@_parents) + Array(parent_params)).uniq
668
717
  path = process_path_for_parent_params(path, parent_params)
669
718
  end
670
719
 
@@ -692,7 +741,7 @@ module Padrino
692
741
  # Merge in option defaults
693
742
  options.reverse_merge!(:default_values => @_defaults)
694
743
 
695
- [path, name, options, route_options]
744
+ [path, name, parent_params, options, route_options]
696
745
  end
697
746
 
698
747
  ##
@@ -758,7 +807,7 @@ module Padrino
758
807
  condition do
759
808
  mime_types = types.map { |t| mime_type(t) }
760
809
  url_format = params[:format].to_sym if params[:format]
761
- accepts = request.accept.map { |a| a.split(";")[0].strip }
810
+ accepts = request.accept.map { |a| a.to_str }
762
811
 
763
812
  # per rfc2616-sec14:
764
813
  # Assume */* if no ACCEPT header is given.
@@ -793,6 +842,21 @@ module Padrino
793
842
  matched_format
794
843
  end
795
844
  end
845
+
846
+ ##
847
+ # Implements CSRF checking when `allow_disabled_csrf` is set to true.
848
+ #
849
+ # This condition is always on, except when it is explicitly switched
850
+ # off.
851
+ #
852
+ # @example
853
+ # post("/", :csrf_protection => false)
854
+ #
855
+ def csrf_protection(on = true)
856
+ if on
857
+ condition { halt 403 if request.env['protection.csrf.failed'] }
858
+ end
859
+ end
796
860
  end
797
861
 
798
862
  ##
@@ -836,7 +900,7 @@ module Padrino
836
900
  else
837
901
  path_params << params
838
902
  end
839
- @route.url(*path_params)
903
+ @route.path(*path_params)
840
904
  end
841
905
 
842
906
  ##
@@ -905,13 +969,19 @@ module Padrino
905
969
  end
906
970
 
907
971
  def dispatch!
908
- static! if settings.static? && (request.get? || request.head?)
909
- route!
972
+ invoke do
973
+ static! if settings.static? && (request.get? || request.head?)
974
+ route!
975
+ end
910
976
  rescue ::Exception => boom
911
- filter! :before
912
- handle_exception!(boom)
977
+ filter! :before if boom.kind_of? ::Sinatra::NotFound
978
+ invoke { @boom_handled = handle_exception!(boom) }
913
979
  ensure
914
- filter! :after unless env['sinatra.static_file']
980
+ @boom_handled or begin
981
+ filter! :after unless env['sinatra.static_file']
982
+ rescue ::Exception => boom
983
+ invoke { handle_exception!(boom) } unless @env['sinatra.error']
984
+ end
915
985
  end
916
986
 
917
987
  def route!(base=settings, pass_block=nil)
@@ -919,9 +989,10 @@ module Padrino
919
989
  if base.compiled_router and match = base.compiled_router.call(@request.env)
920
990
  if match.respond_to?(:each)
921
991
  route_eval do
922
- match[1].each {|k,v| response[k] = v}
992
+ match[1].each { |k,v| response[k] = v }
923
993
  status match[0]
924
994
  route_missing if match[0] == 404
995
+ route_missing if allow = response['Allow'] and allow.include?(request.env['REQUEST_METHOD'])
925
996
  end
926
997
  end
927
998
  else
@@ -6,17 +6,18 @@ module Padrino
6
6
  class Base < Thor
7
7
  include Thor::Actions
8
8
 
9
- class_option :chdir, :type => :string, :aliases => "-c", :desc => "Change to dir before starting"
10
- class_option :environment, :type => :string, :aliases => "-e", :required => true, :default => :development, :desc => "Padrino Environment"
9
+ class_option :chdir, :type => :string, :aliases => "-c", :desc => "Change to dir before starting."
10
+ class_option :environment, :type => :string, :aliases => "-e", :required => true, :default => :development, :desc => "Padrino Environment."
11
11
  class_option :help, :type => :boolean, :desc => "Show help usage"
12
12
 
13
- desc "start", "Starts the Padrino application"
14
- method_option :server, :type => :string, :aliases => "-a", :desc => "Rack Handler (default: autodetect)"
15
- method_option :host, :type => :string, :aliases => "-h", :required => true, :default => "0.0.0.0", :desc => "Bind to HOST address"
16
- method_option :port, :type => :numeric, :aliases => "-p", :required => true, :default => 3000, :desc => "Use PORT"
17
- method_option :daemonize, :type => :boolean, :aliases => "-d", :desc => "Run daemonized in the background"
18
- method_option :pid, :type => :string, :aliases => "-i", :desc => "File to store pid"
19
- method_option :debug, :type => :boolean, :desc => "Set debugging flags"
13
+ desc "start", "Starts the Padrino application (alternatively use 's')."
14
+ map "s" => :start
15
+ method_option :server, :type => :string, :aliases => "-a", :desc => "Rack Handler (default: autodetect)"
16
+ method_option :host, :type => :string, :aliases => "-h", :required => true, :default => '127.0.0.1', :desc => "Bind to HOST address."
17
+ method_option :port, :type => :numeric, :aliases => "-p", :required => true, :default => 3000, :desc => "Use PORT."
18
+ method_option :daemonize, :type => :boolean, :aliases => "-d", :desc => "Run daemonized in the background."
19
+ method_option :pid, :type => :string, :aliases => "-i", :desc => "File to store pid."
20
+ method_option :debug, :type => :boolean, :desc => "Set debugging flags."
20
21
  def start
21
22
  prepare :start
22
23
  require File.expand_path("../adapter", __FILE__)
@@ -24,12 +25,8 @@ module Padrino
24
25
  Padrino::Cli::Adapter.start(options)
25
26
  end
26
27
 
27
- desc "s", "Starts the Padrino application"
28
- def s
29
- invoke :start
30
- end
31
-
32
- desc "stop", "Stops the Padrino application"
28
+ desc "stop", "Stops the Padrino application (alternatively use 'st')."
29
+ map "st" => :stop
33
30
  method_option :pid, :type => :string, :aliases => "-p", :desc => "File to store pid", :default => 'tmp/pids/server.pid'
34
31
  def stop
35
32
  prepare :stop
@@ -37,7 +34,7 @@ module Padrino
37
34
  Padrino::Cli::Adapter.stop(options)
38
35
  end
39
36
 
40
- desc "rake", "Execute rake tasks"
37
+ desc "rake", "Execute rake tasks."
41
38
  method_option :environment, :type => :string, :aliases => "-e", :required => true, :default => :development
42
39
  method_option :list, :type => :string, :aliases => "-T", :desc => "Display the tasks (matching optional PATTERN) with descriptions, then exit."
43
40
  method_option :trace, :type => :boolean, :aliases => "-t", :desc => "Turn on invoke/execute tracing, enable full backtrace."
@@ -51,12 +48,15 @@ module Padrino
51
48
  ARGV.concat(args)
52
49
  puts "=> Executing Rake #{ARGV.join(' ')} ..."
53
50
  load File.expand_path('../rake.rb', __FILE__)
54
- require File.expand_path('config/boot.rb')
55
- PadrinoTasks.init(true)
51
+ Rake.application.init
52
+ Rake.application.instance_variable_set(:@rakefile, __FILE__)
53
+ load File.expand_path('Rakefile')
54
+ Rake.application.top_level
56
55
  end
57
56
 
58
- desc "console", "Boots up the Padrino application irb console"
59
- def console
57
+ desc "console", "Boots up the Padrino application irb console (alternatively use 'c')."
58
+ map "c" => :console
59
+ def console(*args)
60
60
  prepare :console
61
61
  require File.expand_path("../../version", __FILE__)
62
62
  ARGV.clear
@@ -68,12 +68,8 @@ module Padrino
68
68
  IRB.start
69
69
  end
70
70
 
71
- desc "c", "Boots up the Padrino application irb console"
72
- def c(*args)
73
- invoke(:console, args)
74
- end
75
-
76
- desc "generate", "Executes the Padrino generator with given options."
71
+ desc "generate", "Executes the Padrino generator with given options (alternatively use 'gen' or 'g')."
72
+ map ["gen", "g"] => :generate
77
73
  def generate(*args)
78
74
  # Build Padrino g as an alias of padrino-gen
79
75
  begin
@@ -90,23 +86,30 @@ module Padrino
90
86
  end
91
87
  end
92
88
 
93
- desc "g", "Executes the Padrino generator with given options."
94
- def g(*args)
95
- invoke(:generate, args)
96
- end
97
-
98
- desc "gen", "Executes the Padrino generator with given options."
99
- def gen(*args)
100
- invoke(:generate, args)
101
- end
102
-
103
- desc "version", "Show current Padrino Version"
104
- map "-v" => :version, "--version" => :version
89
+ desc "version", "Show current Padrino version."
90
+ map ["-v", "--version"] => :version
105
91
  def version
106
92
  require 'padrino-core/version'
107
93
  puts "Padrino v. #{Padrino.version}"
108
94
  end
109
95
 
96
+ desc "runner", "Run a piece of code in the Padrino application environment (alternatively use 'run' or 'r')."
97
+ map ["run", "r"] => :runner
98
+ def runner(*args)
99
+ prepare :runner
100
+
101
+ code_or_file = args.shift
102
+ abort "Please specify code or file" if code_or_file.nil?
103
+
104
+ require File.expand_path('config/boot.rb')
105
+
106
+ if File.exist?(code_or_file)
107
+ eval(File.read(code_or_file), nil, code_or_file)
108
+ else
109
+ eval(code_or_file)
110
+ end
111
+ end
112
+
110
113
  private
111
114
  def prepare(task)
112
115
  if options.help?