Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Started writing bacon specs before going any further

  • Loading branch information...
commit 39143f05182d7eebdeeb5c8c22532c5663ad3ece 1 parent c2ab2f4
Ivan Porto Carrero authored May 01, 2009

Showing 49 changed files with 1,149 additions and 242 deletions. Show diff stats Hide diff stats

  1. 2  .gitignore
  2. 87  IronMvcSpecs/IronMvcSpecs.stproj
  3. 46  IronMvcSpecs/Rakefile.rb
  4. 8  IronMvcSpecs/bacon_helper.rb
  5. 4  IronMvcSpecs/extensions/extensions.rb
  6. 70  IronMvcSpecs/extensions/ienumerable_extensions_spec.rb
  7. 26  IronMvcSpecs/extensions/object_extensions_spec.rb
  8. 55  IronMvcSpecs/extensions/string_extensions_spec.rb
  9. 152  IronMvcSpecs/lib/amok.rb
  10. 23  IronMvcSpecs/workarounds/Workarounds.cs
  11. 2  IronRubyMvc.Tests/Core/RubyEngineSpec.cs
  12. 10  IronRubyMvc.sln
  13. 7  IronRubyMvc/Controllers/RubyActionMethodSelector.cs
  14. 3  IronRubyMvc/Controllers/RubyControllerDescriptor.cs
  15. 82  IronRubyMvc/Controllers/controller.rb
  16. 8  IronRubyMvc/Core/IPathProvider.cs
  17. 88  IronRubyMvc/Core/IRubyEngine.cs
  18. 131  IronRubyMvc/Core/MvcApplication.cs
  19. 17  IronRubyMvc/Core/MvcScriptHost.cs
  20. 85  IronRubyMvc/Core/PathProviderPAL.cs
  21. 83  IronRubyMvc/Core/RubyEngine.cs
  22. 14  IronRubyMvc/Core/RubyMvcApplication.cs
  23. 102  IronRubyMvc/Core/RubyMvcModule.cs
  24. 36  IronRubyMvc/Core/TypeConverter.cs
  25. 36  IronRubyMvc/Core/VirtualPathProvider.cs
  26. 11  IronRubyMvc/Extensions/IDictionaryExtensions.cs
  27. 143  IronRubyMvc/Extensions/IEnumerableExtensions.cs
  28. 11  IronRubyMvc/Extensions/ObjectExtensions.cs
  29. 6  IronRubyMvc/Extensions/StringExtensions.cs
  30. 10  IronRubyMvc/Helpers/RubyAjaxHelper.cs
  31. 15  IronRubyMvc/System.Web.Mvc.IronRuby.csproj
  32. 2  IronRubyMvcWeb/Default.aspx
  33. 2  IronRubyMvcWeb/Web.config
  34. BIN  dependencies/IronRuby.Libraries.Yaml.dll
  35. BIN  dependencies/IronRuby.Libraries.Yaml.pdb
  36. BIN  dependencies/IronRuby.Libraries.dll
  37. BIN  dependencies/IronRuby.Libraries.pdb
  38. BIN  dependencies/IronRuby.dll
  39. BIN  dependencies/IronRuby.pdb
  40. BIN  dependencies/Microsoft.Scripting.Core.dll
  41. BIN  dependencies/Microsoft.Scripting.Core.pdb
  42. BIN  dependencies/Microsoft.Scripting.ExtensionAttribute.dll
  43. BIN  dependencies/Microsoft.Scripting.ExtensionAttribute.pdb
  44. BIN  dependencies/Microsoft.Scripting.dll
  45. BIN  dependencies/Microsoft.Scripting.pdb
  46. BIN  dependencies/xUnit.BDDExtensions.dll
  47. BIN  dependencies/xUnit.BDDExtensions.pdb
  48. BIN  dependencies/xunit.dll
  49. 14  dependencies/xunit.xml
2  .gitignore
@@ -20,4 +20,4 @@ IronRubyMvc/Controllers/._controller.rb
20 20
 IronRubyMvc/Core/._RubyEngine.cs
21 21
 dependencies/IronRuby.Tests.exe
22 22
 dependencies/IronRuby.Tests.pdb
23  
-IronRubyMvcLibrarySpecs/bin/*.*
  23
+IronMvcSpecs/bin/*.*
87  IronMvcSpecs/IronMvcSpecs.stproj
... ...
@@ -0,0 +1,87 @@
  1
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  2
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
  3
+    <Name>Debug</Name>
  4
+    <OutputPath>Debug\</OutputPath>
  5
+  </PropertyGroup>
  6
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
  7
+    <Name>Release</Name>
  8
+    <OutputPath>Release\</OutputPath>
  9
+  </PropertyGroup>
  10
+  <UsingTask TaskName="Sapphire.Steel.SteelRubyBuild" AssemblyName="SteelBuild, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8a42f26dbbcba2be, processorArchitecture=x86" />
  11
+  <UsingTask TaskName="Sapphire.Steel.SteelRailsBuild" AssemblyName="SteelBuild, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8a42f26dbbcba2be, processorArchitecture=x86" />
  12
+  <Target Name="BuildRails" Inputs="@(EmbeddedRuby)" Outputs="$(MSBuildProjectDirectory)\SyntaxCheck\%(Identity)">
  13
+    <MakeDir Directories="SyntaxCheck" />
  14
+    <SteelRailsBuild ERBFile="@(EmbeddedRuby)" ProjectDirectory="$(MSBuildProjectDirectory)" ERBProcessor="$(ERBProcessor)" ERBFlags="$(ERBFlags)" ERBLibraryFiles="$(ERBLibraryFiles)" ERBTimeout="$(ERBTimeout)" />
  15
+  </Target>
  16
+  <Target Name="BuildRuby" Inputs="@(Ruby)" Outputs="$(MSBuildProjectDirectory)\SyntaxCheck\%(Identity)">
  17
+    <MakeDir Directories="SyntaxCheck" />
  18
+    <SteelRubyBuild RubyFile="@(Ruby)" ProjectDirectory="$(MSBuildProjectDirectory)" RubyInterpreter="$(RubyInterpreter)" RubyInterpreterFlags="$(RubyInterpreterFlags)" RubyLibraryFiles="$(RubyLibraryFiles)" RubyLibraryPaths="$(LibraryPath)" RubyTimeout="$(RubyTimeout)" />
  19
+  </Target>
  20
+  <Target Name="Clean">
  21
+    <RemoveDir Directories="$(MSBuildProjectDirectory)\SyntaxCheck" />
  22
+  </Target>
  23
+  <Target Name="Build" DependsOnTargets="$(BuildDependsOn)" Inputs="@(Ruby); @(EmbeddedRuby)" Outputs="$(MSBuildProjectDirectory)\SyntaxCheck\%(Identity)">
  24
+  </Target>
  25
+  <Target Name="Clean">
  26
+    <RemoveDir Directories="$(MSBuildProjectDirectory)\SyntaxCheck" />
  27
+  </Target>
  28
+  <PropertyGroup>
  29
+    <RebuildDependsOn>
  30
+      Clean;
  31
+      Build;
  32
+    </RebuildDependsOn>
  33
+    <BuildDependsOn>
  34
+      BeforeBuild;
  35
+      BuildRuby; 
  36
+      BuildRails;
  37
+      AfterBuild;
  38
+    </BuildDependsOn>
  39
+    <SteelVersion>1.2</SteelVersion>
  40
+    <ProjectGuid>{4b1e7b70-f827-46a0-9d8d-68498b5ef73d}</ProjectGuid>
  41
+    <AssemblyName>IronMvcSpecs</AssemblyName>
  42
+    <RootNamespace>IronMvcSpecs</RootNamespace>
  43
+  </PropertyGroup>
  44
+  <ItemGroup>
  45
+    <Ruby Include="bacon_helper.rb" />
  46
+    <Ruby Include="extensions\extensions.rb" />
  47
+    <Ruby Include="extensions\ienumerable_extensions_spec.rb" />
  48
+    <Ruby Include="extensions\object_extensions_spec.rb" />
  49
+    <Ruby Include="extensions\string_extensions_spec.rb" />
  50
+    <Ruby Include="lib\amok.rb" />
  51
+    <Ruby Include="Rakefile.rb" />
  52
+  </ItemGroup>
  53
+  <ItemGroup>
  54
+    <Folder Include="Debug" />
  55
+    <Folder Include="lib" />
  56
+    <Folder Include="extensions" />
  57
+    <Folder Include="bin" />
  58
+    <Folder Include="workarounds" />
  59
+  </ItemGroup>
  60
+  <ItemGroup>
  61
+    <Content Include="bin\BugWorkarounds.dll" />
  62
+    <Content Include="bin\BugWorkarounds.pdb" />
  63
+    <Content Include="bin\IronRuby.dll" />
  64
+    <Content Include="bin\IronRuby.Libraries.dll" />
  65
+    <Content Include="bin\IronRuby.Libraries.pdb" />
  66
+    <Content Include="bin\IronRuby.pdb" />
  67
+    <Content Include="bin\Microsoft.Scripting.Core.dll" />
  68
+    <Content Include="bin\Microsoft.Scripting.Core.pdb" />
  69
+    <Content Include="bin\Microsoft.Scripting.dll" />
  70
+    <Content Include="bin\Microsoft.Scripting.ExtensionAttribute.dll" />
  71
+    <Content Include="bin\Microsoft.Scripting.ExtensionAttribute.pdb" />
  72
+    <Content Include="bin\Microsoft.Scripting.pdb" />
  73
+    <Content Include="bin\System.Web.Mvc.IronRuby.dll" />
  74
+    <Content Include="bin\System.Web.Mvc.IronRuby.pdb" />
  75
+    <Content Include="workarounds\Workarounds.cs" />
  76
+  </ItemGroup>
  77
+  <Target Name="Rebuild" DependsOnTargets="$(RebuildDependsOn)" Inputs="@(Ruby)" Outputs="$(MSBuildProjectDirectory)\SyntaxCheck\%(Identity)">
  78
+  </Target>
  79
+  <Target Name="BeforeBuild" Condition="'$(PreBuildEvent)'!='' ">
  80
+    <Exec Command="$(PreBuildEvent)" />
  81
+  </Target>
  82
+  <Target Name="AfterBuild" Condition="'$(PostBuildEvent)'!='' ">
  83
+    <Exec Command="$(PostBuildEvent)" />
  84
+  </Target>
  85
+  <!--<Import Project="$(MSBuildBinPath)\Microsoft.Common.targets" />-->
  86
+  <Target Name="ResolveAssemblyReferences" />
  87
+</Project>
46  IronMvcSpecs/Rakefile.rb
... ...
@@ -0,0 +1,46 @@
  1
+require 'ftools'
  2
+
  3
+def tgt_dir
  4
+ File.dirname(__FILE__) + "/bin"
  5
+end 
  6
+  
  7
+def mono?
  8
+  !ENV['mono'].nil? && ENV['mono'] > 0
  9
+end
  10
+
  11
+desc "The default task is to run all the specs"
  12
+task :default => :spec
  13
+
  14
+desc "Runs all the specs"
  15
+task :spec => [:copy_binaries, :workarounds, 'spec:extensions']
  16
+
  17
+namespace :spec do 
  18
+  desc "runs the specs for the extensions"
  19
+  task :extensions do
  20
+    puts "starting extension specs"
  21
+    system "ibacon #{Dir.glob('extensions/**/*_spec.rb').join(' ')}"
  22
+#    specs = Dir.glob('extensions/**/*_spec.rb')
  23
+#    require 'rubygems'
  24
+#    require 'bacon'
  25
+#    Bacon.extend Bacon.const_get('SpecDoxOutput')
  26
+#    Bacon.summary_on_exit
  27
+#    
  28
+#    specs.each { |spec|
  29
+#      load File.dirname(__FILE__) + "/#{spec}"
  30
+#    }
  31
+  end
  32
+end
  33
+
  34
+desc "Copies the binaries from System.Web.Mvc.IronRuby to the specs folder"
  35
+task :copy_binaries do
  36
+  src_dir = File.expand_path(File.dirname(__FILE__) + "/../IronRubyMvc/bin/Debug")
  37
+  files = Dir.glob("#{src_dir}/*")
  38
+  files.each { |f| File.copy("#{f}", "#{tgt_dir}/#{File.basename(f)}") }
  39
+end
  40
+
  41
+desc "Compiles the workarounds"
  42
+task :workarounds do
  43
+  Dir.chdir(File.dirname(__FILE__))
  44
+  files = Dir.glob("workarounds/*.cs").collect { |f| f.gsub(/\//, "\\")  }.join(" ")
  45
+  system "csc /noconfig /target:library /debug+ /debug:full /out:bin\\BugWorkarounds.dll /reference:bin\\IronRuby.dll /reference:bin\\Microsoft.Scripting.dll /reference:bin\\Microsoft.Scripting.Core.dll /reference:bin\\System.Web.Mvc.IronRuby.dll #{files}"
  46
+end
8  IronMvcSpecs/bacon_helper.rb
... ...
@@ -0,0 +1,8 @@
  1
+$: << File.dirname(__FILE__) + '/bin'
  2
+require 'bacon'
  3
+require 'mscorlib'
  4
+require File.dirname(__FILE__) + "/lib/amok.rb"
  5
+
  6
+#load_assembly 'System.Web.Mvc.IronRuby, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
  7
+load_assembly 'System.Web.Mvc.IronRuby'
  8
+load_assembly 'BugWorkarounds'
4  IronMvcSpecs/extensions/extensions.rb
... ...
@@ -0,0 +1,4 @@
  1
+require File.dirname(__FILE__) + "/../bacon_helper.rb"
  2
+
  3
+include System::Web::Mvc::IronRuby::Extensions
  4
+include BugWorkarounds
70  IronMvcSpecs/extensions/ienumerable_extensions_spec.rb
... ...
@@ -0,0 +1,70 @@
  1
+require File.dirname(__FILE__) + "/extensions.rb"
  2
+
  3
+describe "IEnumerableExtensions" do
  4
+  
  5
+  before do
  6
+    @collection = [1, 2, 3, 4, 5, 6, 7, 8]
  7
+    @generic_collection = System::Collections::Generic::List.of(Fixnum).new
  8
+    @generic_collection.add 1
  9
+    @generic_collection.add 2
  10
+    @generic_collection.add 3
  11
+    @generic_collection.add 4
  12
+    @generic_collection.add 5
  13
+    @generic_collection.add 6
  14
+    @generic_collection.add 7
  15
+    @generic_collection.add 8
  16
+    @generic_collection.add 9
  17
+  end
  18
+  
  19
+  describe "iteration" do
  20
+    it "should iterate over an untyped collection" do
  21
+      counter, result = 0, 0
  22
+      p = Proc.new {|item| counter += 1; result += item }
  23
+      iterator = Workarounds.wrap_proc(p)
  24
+      IEnumerableExtensions.for_each(@collection, iterator)
  25
+      counter.should == 8
  26
+      result.should == 36
  27
+    end
  28
+    
  29
+    it "should iterate over a generic collection" do
  30
+      counter, result = 0, 0
  31
+      p = Proc.new {|item| counter += 1; result += item }
  32
+      iterator = Workarounds.method(:wrap_proc).of(Fixnum).call(p)
  33
+      IEnumerableExtensions.method(:for_each).of(Fixnum).call(@generic_collection, iterator)
  34
+      counter.should == 9
  35
+      result.should == 45
  36
+    end
  37
+  end
  38
+  
  39
+  describe "empty checking" do
  40
+  
  41
+    it "should raise an ArgumentException for a non-generic method call with null" do
  42
+      should.raise(System::NullReferenceException){ Workarounds.is_empty(nil) }
  43
+    end
  44
+    
  45
+    it "should raise an ArgumentException for a non-generic method call with null" do
  46
+      should.raise(System::NullReferenceException){ Workarounds.method(:is_empty).of(System::String).call(nil) }
  47
+    end
  48
+    
  49
+    it "should be true for an empty non-generic collection" do
  50
+      IEnumerableExtensions.is_empty([]).should.be.true?
  51
+    end
  52
+    
  53
+    it "should be true for an empty generic collection" do
  54
+      coll = System::Collections::Generic::List.of(String).new
  55
+      IEnumerableExtensions.method(:is_empty).of(String).call(coll).should.be.true?
  56
+    end
  57
+    
  58
+    it "should be false for an non-empty non-generic collection" do
  59
+      IEnumerableExtensions.is_empty([3]).should.be.false?
  60
+    end
  61
+    
  62
+    it "should be false for a non-empty generic collection" do
  63
+      coll = System::Collections::Generic::List.of(String).new
  64
+      coll.add "a string"
  65
+      IEnumerableExtensions.method(:is_empty).of(String).call(coll).should.be.false?
  66
+    end
  67
+  
  68
+  end 
  69
+  
  70
+end
26  IronMvcSpecs/extensions/object_extensions_spec.rb
... ...
@@ -0,0 +1,26 @@
  1
+require File.dirname(__FILE__) + '/extensions.rb'
  2
+
  3
+describe "ObjectExtensions" do 
  4
+  
  5
+  describe "when asking for null" do
  6
+    it "should return true for a null value" do
  7
+       Workarounds.is_null(nil).should.be.true?
  8
+    end
  9
+    
  10
+    it "should return false for an object instance" do
  11
+      ObjectExtensions.is_null(System::Object.new).should.be.false?
  12
+    end
  13
+  end
  14
+  
  15
+  describe "when asking for not null" do
  16
+    it "should return false for a null value" do
  17
+      Workarounds.is_not_null(nil).should.be.false?
  18
+    end
  19
+    
  20
+    it "should return true for an object instance" do
  21
+      ObjectExtensions.is_not_null(Object.new).should.be.true?
  22
+    end
  23
+  end
  24
+ 
  25
+  
  26
+end
55  IronMvcSpecs/extensions/string_extensions_spec.rb
... ...
@@ -0,0 +1,55 @@
  1
+require File.dirname(__FILE__) + '/extensions.rb'
  2
+
  3
+describe "StringExtensions" do 
  4
+  
  5
+  describe "when asking for null or blank" do
  6
+    it "should return true for a null value" do
  7
+      Workarounds.is_null_or_blank(nil).should.be.true?
  8
+    end
  9
+    
  10
+    it "should return true for an empty value" do
  11
+      StringExtensions.is_null_or_blank("").should.be.true?
  12
+    end
  13
+    
  14
+    it "should return true when the string contains only spaces" do
  15
+      StringExtensions.is_null_or_blank("      ").should.be.true?
  16
+    end
  17
+    
  18
+    it "should return false when the string contains a value" do
  19
+      StringExtensions.is_null_or_blank("a string value").should.be.false?
  20
+    end
  21
+        
  22
+  end
  23
+  
  24
+  describe "when asking for not null or blank" do
  25
+    
  26
+    it "should return false when value is null" do
  27
+      Workarounds.is_not_null_or_blank(nil).should.be.false?
  28
+    end
  29
+    
  30
+    it "should return false for an empty value" do
  31
+      StringExtensions.is_not_null_or_blank("").should.be.false?
  32
+    end
  33
+    
  34
+    it "should return false when the string contains only spaces" do
  35
+      StringExtensions.is_not_null_or_blank("      ").should.be.false?
  36
+    end
  37
+    
  38
+    it "should return true when the string contains a value" do
  39
+      StringExtensions.is_not_null_or_blank("a string value").should.be.true?
  40
+    end
  41
+    
  42
+  end
  43
+  
  44
+  describe "when asking to format a string" do 
  45
+    
  46
+    it "should return a properly formatted string" do
  47
+      expected = "This is the 1 and only Format test at #{System::DateTime.now.to_short_date_string}".to_clr_string
  48
+      actual = StringExtensions.formatted_with("This is the {0} and only {1} test at {2}".to_clr_string, 1, "Format", System::DateTime.now.to_short_date_string)
  49
+      
  50
+      expected.should == actual
  51
+    end
  52
+    
  53
+  end
  54
+
  55
+end
152  IronMvcSpecs/lib/amok.rb
... ...
@@ -0,0 +1,152 @@
  1
+# Amok -- a compact mock library
  2
+
  3
+# Copyright (C) 2008 Christian Neukirchen <purl.org/net/chneukirchen>
  4
+#
  5
+# Amok is freely distributable under the terms of an MIT-style license.
  6
+# See COPYING or http://www.opensource.org/licenses/mit-license.php.
  7
+
  8
+class Amok
  9
+  VERSION = '0.1'
  10
+  
  11
+  attr_reader :obj
  12
+  
  13
+  class Failed < RuntimeError
  14
+    attr_accessor :errors
  15
+  end
  16
+  
  17
+  def self.with(obj)
  18
+    mock = new(obj)
  19
+    yield obj, mock
  20
+    mock.validate
  21
+  end
  22
+  
  23
+  def self.make(hash, &block)
  24
+    a = new(Object.new, &block)
  25
+    hash.each { |key, value| a.on(key) { value } }
  26
+    a.obj
  27
+  end
  28
+  
  29
+  @@uuid = 0
  30
+  def uuid
  31
+    @@uuid += 1
  32
+  end
  33
+  
  34
+  def initialize(obj, &block)
  35
+    @obj = obj
  36
+    @called = {}
  37
+    @previous = {}
  38
+    instance_eval(&block)  if block
  39
+  end
  40
+  
  41
+  def on(method=nil, args=nil, n=nil, &block)
  42
+    return NiceProxy.new(self, n)  unless method || block
  43
+    
  44
+    called = @called
  45
+    id = [method, args]
  46
+    called[id] = n
  47
+    _previous = @previous
  48
+    
  49
+    mock = self
  50
+    (class << @obj; self; end).class_eval {
  51
+      if block
  52
+        current = "__current_#{method}_#{mock.uuid}__amok__"
  53
+        define_method(current, &block)
  54
+      end
  55
+      begin
  56
+        previous = "__previous_#{method}_#{mock.uuid}__amok__"
  57
+        alias_method previous, method
  58
+      rescue NameError
  59
+        previous = nil
  60
+      end
  61
+      _previous[method] ||= previous
  62
+      define_method(method) { |*actual_args|
  63
+        if args.nil? || args == actual_args
  64
+          case called[id]
  65
+          when Numeric;  called[id] -= 1
  66
+          when false;    called[id] = true
  67
+          end
  68
+          __send__(current || previous, *actual_args)
  69
+        else
  70
+          __send__(previous, *actual_args)
  71
+        end
  72
+      }
  73
+    }
  74
+  end
  75
+  
  76
+  def previous(method, *args, &block)
  77
+    @obj.__send__(@previous[method], *args, &block)
  78
+  end
  79
+  
  80
+  def need(method=nil, args=nil, n=false, &block)
  81
+    unless block
  82
+      case method
  83
+      when nil;        NiceProxy.new(self, n)        # mock.need.foo
  84
+      when Numeric;    NiceProxy.new(self, method)   # mock.need(3).foo
  85
+      end
  86
+    else
  87
+      on(method, args, n, &block)
  88
+    end
  89
+  end
  90
+  
  91
+  def never(method=nil, args=nil)
  92
+    return NiceProxy.new(self, 0)  if !method
  93
+    on(method, args, 0) {
  94
+      # should we raise here?
  95
+    }
  96
+  end
  97
+  
  98
+  def errors
  99
+    @called.reject { |k, v|
  100
+      v == 0 ||                 # run the right number of times
  101
+      v == true ||              # run at all
  102
+      v == nil                  # run? who cares?
  103
+    }.map { |(m, a), v|
  104
+      msg = m.to_s
  105
+      msg << "(#{a.map { |x| x.inspect }.join(", ")})"  if a
  106
+      if v == false
  107
+        msg << " was not called."
  108
+      else
  109
+        msg << " was called #{v.abs} times #{v < 0 ? "too often" : "too few"}."
  110
+      end
  111
+    }
  112
+  end
  113
+  
  114
+  def successful?
  115
+    errors.empty?
  116
+  end
  117
+  
  118
+  def validate
  119
+    unless successful?
  120
+      ex = Failed.new(errors.join("  "))
  121
+      ex.errors = errors.dup
  122
+      raise ex
  123
+    end
  124
+  end
  125
+  
  126
+  def cleanup!
  127
+    _previous = @previous
  128
+    (class << @obj; self; end).class_eval {
  129
+      _previous.each { |old, new|
  130
+        new ? alias_method(old, new) : undef_method(old)
  131
+      }
  132
+      methods.each { |m| undef_method  if m =~ /__amok__\Z/ }
  133
+    }
  134
+    @obj
  135
+  end
  136
+  
  137
+  class NiceProxy
  138
+    instance_methods.each { |name|
  139
+      undef_method name  unless name =~ /^__|^instance_eval$/
  140
+    }
  141
+    
  142
+    def initialize(obj, n=nil)
  143
+      @obj, @n = obj, n
  144
+    end
  145
+    
  146
+    def method_missing(name, *args, &block)
  147
+      args = nil  if args.empty?   # allow any arguments when none are mentioned
  148
+      @obj.on(name, args, @n, &block)
  149
+      self
  150
+    end
  151
+  end
  152
+end
23  IronMvcSpecs/workarounds/Workarounds.cs
... ...
@@ -0,0 +1,23 @@
  1
+using System;
  2
+using System.Web.Mvc.IronRuby.Extensions;
  3
+using IronRuby.Builtins;
  4
+using System.Collections;
  5
+using System.Collections.Generic;
  6
+
  7
+namespace BugWorkarounds
  8
+{
  9
+    public static class Workarounds
  10
+    {
  11
+        // IronRuby currently is a little bit confused about Actions and extension methods when called with nil/null
  12
+        // These methods get around those confusions
  13
+        public static bool IsNull(object value) { return value.IsNull(); }
  14
+        public static bool IsNotNull(object value) { return value.IsNotNull(); }
  15
+        public static bool IsNullOrBlank(string value) { return value.IsNullOrBlank(); }
  16
+        public static bool IsNotNullOrBlank(string value) { return value.IsNotNullOrBlank(); }
  17
+        public static bool IsEmpty(IEnumerable collection) { return collection.IsEmpty(); }
  18
+        public static bool IsEmpty<T>(IEnumerable<T> collection) { return collection.IsEmpty(); }
  19
+        public static Action<object> WrapProc(Proc proc) { return obj => proc.Call(obj); }
  20
+        public static Action<T> WrapProc<T>(Proc proc) { return obj => proc.Call(obj); }
  21
+    }
  22
+
  23
+}
2  IronRubyMvc.Tests/Core/RubyEngineSpec.cs
@@ -41,7 +41,7 @@ protected override void EstablishContext()
41 41
 
42 42
         protected override void Because()
43 43
         {
44  
-            _engine = RubyEngine.InitializeIronRubyMvc(_pathProvider, "~/routes.rb", path => new TestStreamContentProvider(path));
  44
+            _engine = RubyEngine.InitializeIronRubyMvc(_pathProvider, "~/routes.rb");
45 45
         }
46 46
         
47 47
 
10  IronRubyMvc.sln
@@ -13,6 +13,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
13 13
 		README.markdown = README.markdown
14 14
 	EndProjectSection
15 15
 EndProject
  16
+Project("{325B8569-0C7C-4A6A-8AF8-89C3B6BC9E74}") = "IronMvcSpecs", "IronMvcSpecs\IronMvcSpecs.stproj", "{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}"
  17
+EndProject
16 18
 Global
17 19
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 20
 		Debug_Signed|Any CPU = Debug_Signed|Any CPU
@@ -45,6 +47,14 @@ Global
45 47
 		{13CD326E-5C1A-4404-A1AB-8D0BA6D9FDF9}.Release_Signed|Any CPU.Build.0 = Release_Signed|Any CPU
46 48
 		{13CD326E-5C1A-4404-A1AB-8D0BA6D9FDF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 49
 		{13CD326E-5C1A-4404-A1AB-8D0BA6D9FDF9}.Release|Any CPU.Build.0 = Release|Any CPU
  50
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Debug_Signed|Any CPU.ActiveCfg = Debug|Any CPU
  51
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Debug_Signed|Any CPU.Build.0 = Debug|Any CPU
  52
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
  53
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Debug|Any CPU.Build.0 = Debug|Any CPU
  54
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Release_Signed|Any CPU.ActiveCfg = Release|Any CPU
  55
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Release_Signed|Any CPU.Build.0 = Release|Any CPU
  56
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Release|Any CPU.ActiveCfg = Release|Any CPU
  57
+		{4B1E7B70-F827-46A0-9D8D-68498B5EF73D}.Release|Any CPU.Build.0 = Release|Any CPU
48 58
 	EndGlobalSection
49 59
 	GlobalSection(SolutionProperties) = preSolution
50 60
 		HideSolutionNode = FALSE
7  IronRubyMvc/Controllers/RubyActionMethodSelector.cs
... ...
@@ -1,3 +1,4 @@
  1
+extern alias clr3;
1 2
 #region Usings
2 3
 
3 4
 using System.Collections;
@@ -7,6 +8,8 @@
7 8
 using System.Web.Mvc.IronRuby.Extensions;
8 9
 using IronRuby.Builtins;
9 10
 
  11
+using clr3::System.Linq;
  12
+
10 13
 #endregion
11 14
 
12 15
 namespace System.Web.Mvc.IronRuby.Controllers
@@ -54,7 +57,7 @@ private void PopulateLookupTables(IEnumerable<string> methodNames)
54 57
             var methodAliases = (Hash) _rubyEngine.CallMethod(ControllerClass, "name_selectors");
55 58
             AliasedMethods = methodAliases.Map(pair => KeyValuePairFor(pair));
56 59
             NonAliasedMethods =
57  
-                methodNames.Where(
  60
+                clr3::System.Linq.Enumerable.Where(methodNames,
58 61
                     method =>
59 62
                     AliasedMethods.DoesNotContain(
60 63
                         pair => String.Equals(pair.Key, method.Underscore(), StringComparison.OrdinalIgnoreCase) || String.Equals(pair.Key, method.Pascalize(), StringComparison.OrdinalIgnoreCase)
@@ -77,7 +80,7 @@ public string FindActionMethod(ControllerContext controllerContext, string actio
77 80
             PopulateLookupTables(controllerContext); // dynamic languages can add methods at runtime
78 81
             var methodsMatchingName = GetMatchingAliasedMethods(controllerContext, actionName);
79 82
             methodsMatchingName.AddRange(
80  
-                NonAliasedMethods.Where(
  83
+                clr3::System.Linq.Enumerable.Where(NonAliasedMethods,
81 84
                     name => String.Equals(name, actionName.Underscore(), StringComparison.OrdinalIgnoreCase) || String.Equals(name, actionName.Pascalize(), StringComparison.OrdinalIgnoreCase)));
82 85
             var finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);
83 86
 
3  IronRubyMvc/Controllers/RubyControllerDescriptor.cs
... ...
@@ -1,9 +1,10 @@
  1
+extern alias clr3;
1 2
 #region Usings
2 3
 
3 4
 using System.Web.Mvc.IronRuby.Core;
4 5
 using System.Web.Mvc.IronRuby.Extensions;
5 6
 using IronRuby.Builtins;
6  
-
  7
+using clr3::System.Linq;
7 8
 #endregion
8 9
 
9 10
 namespace System.Web.Mvc.IronRuby.Controllers
82  IronRubyMvc/Controllers/controller.rb
@@ -2,6 +2,55 @@ def debugger
2 2
     System::Diagnostics::Debugger.break if System::Diagnostics::Debugger.launch
3 3
 end
4 4
 
  5
+module System
  6
+
  7
+  module Web 
  8
+    class HttpRequestBase
  9
+
  10
+      def post?
  11
+        self.http_method.to_s.downcase.to_sym == :post
  12
+      end
  13
+      
  14
+      def put?
  15
+        self.http_method.to_s.downcase.to_sym == :put
  16
+      end
  17
+      
  18
+      def get?
  19
+        self.http_method.to_s.downcase.to_sym == :get
  20
+      end
  21
+      
  22
+      def delete?
  23
+        self.http_method.to_s.downcase.to_sym == :delete
  24
+      end
  25
+      
  26
+      def head?
  27
+        self.http_method.to_s.downcase.to_sym == :head
  28
+      end
  29
+    end
  30
+  end
  31
+  
  32
+  class Object
  33
+
  34
+    class << self
  35
+        
  36
+      def create_from_hash(options)
  37
+        result = self.new
  38
+        result.populate_from_hash options
  39
+        result
  40
+      end
  41
+      
  42
+    end
  43
+    
  44
+    def populate_from_hash(options)
  45
+      options.each do |k, v|
  46
+        mn = "#{k}=".to_sym
  47
+        self.send(mn, v) if self.respond_to?(mn)
  48
+      end
  49
+    end
  50
+  end
  51
+
  52
+end
  53
+
5 54
 module IronRubyMvc
6 55
     
7 56
     module Controllers
@@ -222,6 +271,35 @@ def self.included(base)
222 271
         
223 272
     end
224 273
     
  274
+    class PropertyDescriptor
  275
+      
  276
+      attr_accessor :name
  277
+      
  278
+    end
  279
+    
  280
+    class DefaultModelBinder
  281
+      def initialize(target, values)
  282
+        @target = target
  283
+        @values = values
  284
+      end
  285
+      
  286
+      def bind
  287
+        @target
  288
+      end
  289
+      
  290
+      def self.bind(target, values)
  291
+        binder = DefaultModelBinder.new target, values
  292
+        
  293
+        binder.bind
  294
+      end
  295
+      
  296
+      private
  297
+      
  298
+      def has_property?
  299
+        target.get_type
  300
+      end
  301
+    end
  302
+    
225 303
     #module Controllers
226 304
     
227 305
     class Controller < System::Web::Mvc::IronRuby::Controllers::RubyController
@@ -235,9 +313,7 @@ def fill_view_data
235 313
             instance_variables.each { |varname| view_data.add(varname[1..-1], instance_variable_get(varname.to_sym)) }
236 314
         end
237 315
         
238  
-        def post?
239  
-            controller_context.http_context.request.http_method.to_s.downcase.to_sym == :post
240  
-        end
  316
+        
241 317
         
242 318
     end
243 319
     
8  IronRubyMvc/Core/IPathProvider.cs
@@ -10,7 +10,15 @@ public interface IPathProvider
10 10
     {
11 11
         string ApplicationPhysicalPath { get; }
12 12
         bool FileExists(string filePath);
  13
+        bool DirectoryExists(string dirPath);
  14
+        string[] GetDirectories(string path, string searchPattern);
  15
+        string[] GetFiles(string path, string searchPattern);
13 16
         Stream Open(string filePath);
14 17
         string MapPath(string filePath);
  18
+        bool IsAbsolutePath(string path);
  19
+        string GetFullPath(string path);
  20
+
  21
+        Stream Open(string path, FileMode mode, FileAccess access, FileShare share);
  22
+        Stream Open(string path, FileMode mode, FileAccess access, FileShare share, int size);
15 23
     }
16 24
 }
88  IronRubyMvc/Core/IRubyEngine.cs
@@ -15,22 +15,6 @@ namespace System.Web.Mvc.IronRuby.Core
15 15
     /// </summary>
16 16
     public interface IRubyEngine
17 17
     {
18  
-//        /// <summary>
19  
-//        /// Loads the controller.
20  
-//        /// </summary>
21  
-//        /// <param name="requestContext">The request context.</param>
22  
-//        /// <param name="controllerName">Name of the controller.</param>
23  
-//        /// <returns></returns>
24  
-//        RubyController LoadController(RequestContext requestContext, string controllerName);
25  
-//
26  
-//        /// <summary>
27  
-//        /// Configures the controller.
28  
-//        /// </summary>
29  
-//        /// <param name="rubyClass">The ruby class.</param>
30  
-//        /// <param name="requestContext">The request context.</param>
31  
-//        /// <returns></returns>
32  
-//        RubyController ConfigureController(RubyClass rubyClass, RequestContext requestContext);
33  
-
34 18
         /// <summary>
35 19
         /// Calls the method.
36 20
         /// </summary>
@@ -40,16 +24,6 @@ public interface IRubyEngine
40 24
         /// <returns></returns>
41 25
         object CallMethod(object receiver, string message, params object[] args);
42 26
 
43  
-//        /// <summary>
44  
-//        /// Determines whether the specified controller as the action.
45  
-//        /// </summary>
46  
-//        /// <param name="controller">The controller.</param>
47  
-//        /// <param name="actionName">Name of the action.</param>
48  
-//        /// <returns>
49  
-//        /// 	<c>true</c> if the specified controller has the action; otherwise, <c>false</c>.
50  
-//        /// </returns>
51  
-//        bool HasControllerAction(RubyController controller, string actionName);
52  
-
53 27
         /// <summary>
54 28
         /// Gets the method names for the controller class.
55 29
         /// </summary>
@@ -86,6 +60,68 @@ public interface IRubyEngine
86 60
         object ExecuteScript(string script, ScriptScope scope);
87 61
 
88 62
         /// <summary>
  63
+        /// Executes the file.
  64
+        /// </summary>
  65
+        /// <param name="path">The path.</param>
  66
+        /// <param name="scope">The scope.</param>
  67
+        /// <param name="throwIfNotExist">if set to <c>true</c> [throw if not exist].</param>
  68
+        /// <returns></returns>
  69
+        object ExecuteFile(string path, ScriptScope scope, bool throwIfNotExist);
  70
+
  71
+        /// <summary>
  72
+        /// Executes the file.
  73
+        /// </summary>
  74
+        /// <typeparam name="T"></typeparam>
  75
+        /// <param name="path">The path.</param>
  76
+        /// <param name="throwIfNotExist">if set to <c>true</c> [throw if not exist].</param>
  77
+        /// <returns></returns>
  78
+        T ExecuteFile<T>(string path, bool throwIfNotExist);
  79
+
  80
+
  81
+        /// <summary>
  82
+        /// Executes the file.
  83
+        /// </summary>
  84
+        /// <typeparam name="T"></typeparam>
  85
+        /// <param name="path">The path.</param>
  86
+        /// <returns></returns>
  87
+        T ExecuteFile<T>(string path);
  88
+
  89
+        /// <summary>
  90
+        /// Executes the script.
  91
+        /// </summary>
  92
+        /// <typeparam name="T"></typeparam>
  93
+        /// <param name="script">The script.</param>
  94
+        /// <returns></returns>
  95
+        T ExecuteScript<T>(string script);
  96
+
  97
+        /// <summary>
  98
+        /// Executes the script.
  99
+        /// </summary>
  100
+        /// <typeparam name="T"></typeparam>
  101
+        /// <param name="script">The script.</param>
  102
+        /// <param name="scope">The scope.</param>
  103
+        /// <returns></returns>
  104
+        T ExecuteScript<T>(string script, ScriptScope scope);
  105
+
  106
+        /// <summary>
  107
+        /// Executes the file.
  108
+        /// </summary>
  109
+        /// <typeparam name="T"></typeparam>
  110
+        /// <param name="path">The path.</param>
  111
+        /// <param name="scope">The scope.</param>
  112
+        /// <param name="throwIfNotExist">if set to <c>true</c> [throw if not exist].</param>
  113
+        /// <returns></returns>
  114
+        T ExecuteFile<T>(string path, ScriptScope scope, bool throwIfNotExist);
  115
+
  116
+
  117
+        /// <summary>
  118
+        /// Executes the file.
  119
+        /// </summary>
  120
+        /// <param name="path">The path.</param>
  121
+        /// <returns></returns>
  122
+        object ExecuteFile(string path);
  123
+
  124
+        /// <summary>
89 125
         /// Defines the read only global variable.
90 126
         /// </summary>
91 127
         /// <param name="variableName">Name of the variable.</param>
131  IronRubyMvc/Core/MvcApplication.cs
... ...
@@ -0,0 +1,131 @@
  1
+namespace System.Web.Mvc.IronRuby.Core
  2
+{
  3
+    public abstract class MvcApplication 
  4
+    {
  5
+        public virtual void Start(object sender, EventArgs e)
  6
+        {
  7
+            //intentionally left blank for a better overriding experience
  8
+        }
  9
+
  10
+        public virtual void Error(object sender, EventArgs e)
  11
+        {
  12
+            //intentionally left blank for a better overriding experience
  13
+        }
  14
+
  15
+        public virtual void AcquireRequestState(object sender, EventArgs e)
  16
+        {
  17
+            //intentionally left blank for a better overriding experience
  18
+        }
  19
+
  20
+        public virtual void AuthenticateRequest(object sender, EventArgs e)
  21
+        {
  22
+            //intentionally left blank for a better overriding experience
  23
+        }
  24
+
  25
+        public virtual void AuthorizeRequest(object sender, EventArgs e)
  26
+        {
  27
+            //intentionally left blank for a better overriding experience
  28
+        }
  29
+
  30
+        public virtual void BeginRequest(object sender, EventArgs e)
  31
+        {
  32
+            //intentionally left blank for a better overriding experience
  33
+        }
  34
+
  35
+        public virtual void Disposed(object sender, EventArgs e)
  36
+        {
  37
+            //intentionally left blank for a better overriding experience
  38
+        }
  39
+
  40
+        public virtual void EndRequest(object sender, EventArgs e)
  41
+        {
  42
+            //intentionally left blank for a better overriding experience
  43
+        }
  44
+
  45
+        public virtual void LogRequest(object sender, EventArgs e)
  46
+        {
  47
+            //intentionally left blank for a better overriding experience
  48
+        }
  49
+
  50
+        public virtual void PostAcquireRequestState(object sender, EventArgs e)
  51
+        {
  52
+            //intentionally left blank for a better overriding experience
  53
+        }
  54
+
  55
+        public virtual void MapRequestHandler(object sender, EventArgs e)
  56
+        {
  57
+            //intentionally left blank for a better overriding experience
  58
+        }
  59
+
  60
+        public virtual void PostAuthenticateRequest(object sender, EventArgs e)
  61
+        {
  62
+            //intentionally left blank for a better overriding experience
  63
+        }
  64
+
  65
+        public virtual void PostAuthorizeRequest(object sender, EventArgs e)
  66
+        {
  67
+            //intentionally left blank for a better overriding experience
  68
+        }
  69
+
  70
+        public virtual void PostLogRequest(object sender, EventArgs e)
  71
+        {
  72
+            //intentionally left blank for a better overriding experience
  73
+        }
  74
+
  75
+        public virtual void PostMapRequestHandler(object sender, EventArgs e)
  76
+        {
  77
+            //intentionally left blank for a better overriding experience
  78
+        }
  79
+
  80
+        public virtual void PostReleaseRequestState(object sender, EventArgs e)
  81
+        {
  82
+            //intentionally left blank for a better overriding experience
  83
+        }
  84
+
  85
+        public virtual void PostRequestHandlerExecute(object sender, EventArgs e)
  86
+        {
  87
+            //intentionally left blank for a better overriding experience
  88
+        }
  89
+
  90
+        public virtual void PostResolveRequestCache(object sender, EventArgs e)
  91
+        {
  92
+            //intentionally left blank for a better overriding experience
  93
+        }
  94
+
  95
+        public virtual void PostUpdateRequestCache(object sender, EventArgs e)
  96
+        {
  97
+            //intentionally left blank for a better overriding experience
  98
+        }
  99
+
  100
+        public virtual void PreRequestHandlerExecute(object sender, EventArgs e)
  101
+        {
  102
+            //intentionally left blank for a better overriding experience
  103
+        }
  104
+
  105
+        public virtual void PreSendRequestContent(object sender, EventArgs e)
  106
+        {
  107
+            //intentionally left blank for a better overriding experience
  108
+        }
  109
+
  110
+        public virtual void PreSendRequestHeaders(object sender, EventArgs e)
  111
+        {
  112
+            //intentionally left blank for a better overriding experience
  113
+        }
  114
+
  115
+        public virtual void ReleaseRequestState(object sender, EventArgs e)
  116
+        {
  117
+            //intentionally left blank for a better overriding experience
  118
+        }
  119
+
  120
+        public virtual void ResolveRequestCache(object sender, EventArgs e)
  121
+        {
  122
+            //intentionally left blank for a better overriding experience
  123
+        }
  124
+
  125
+        public virtual void UpdateRequestCache(object sender, EventArgs e)
  126
+        {
  127
+            //intentionally left blank for a better overriding experience
  128
+        }
  129
+
  130
+    }
  131
+}
17  IronRubyMvc/Core/MvcScriptHost.cs
... ...
@@ -0,0 +1,17 @@
  1
+using Microsoft.Scripting.Hosting;
  2
+
  3
+namespace System.Web.Mvc.IronRuby.Core
  4
+{
  5
+    public class MvcScriptHost : ScriptHost
  6
+    {
  7
+        public MvcScriptHost(){}
  8
+
  9
+        public override Microsoft.Scripting.PlatformAdaptationLayer PlatformAdaptationLayer
  10
+        {
  11
+            get
  12
+            {
  13
+                return PathProviderPal.PAL;
  14
+            }
  15
+        }
  16
+    }
  17
+}
85  IronRubyMvc/Core/PathProviderPAL.cs
... ...
@@ -0,0 +1,85 @@
  1
+#region Usings
  2
+
  3
+using System.IO;
  4
+using System.Reflection;
  5
+using System.Web.Mvc.IronRuby.Extensions;
  6
+using Microsoft.Scripting;
  7
+
  8
+#endregion
  9
+
  10
+namespace System.Web.Mvc.IronRuby.Core
  11
+{
  12
+    public class PathProviderPal : PlatformAdaptationLayer
  13
+    {
  14
+        internal static PathProviderPal PAL = new PathProviderPal(new VirtualPathProvider());
  15
+        private readonly IPathProvider _pathProvider;
  16
+
  17
+        protected PathProviderPal(IPathProvider pathProvider)
  18
+        {
  19
+            _pathProvider = pathProvider;
  20
+        }
  21
+
  22
+        public override string CurrentDirectory
  23
+        {
  24
+            get { return _pathProvider.ApplicationPhysicalPath; }
  25
+        }
  26
+
  27
+        internal static PathProviderPal Create(IPathProvider pathProvider)
  28
+        {
  29
+            pathProvider.EnsureArgumentNotNull("pathProvider");
  30
+            PAL = new PathProviderPal(pathProvider);
  31
+
  32
+            return PAL;
  33
+        }
  34
+
  35
+        public override bool DirectoryExists(string path)
  36
+        {
  37
+            return _pathProvider.DirectoryExists(path);
  38
+        }
  39
+
  40
+        public override bool FileExists(string path)
  41
+        {
  42
+            return _pathProvider.FileExists(path);
  43
+        }
  44
+
  45
+        public override string[] GetDirectories(string path, string searchPattern)
  46
+        {
  47
+            return _pathProvider.GetDirectories(path, searchPattern);
  48
+        }
  49
+
  50
+        public override string[] GetFiles(string path, string searchPattern)
  51
+        {
  52
+            return _pathProvider.GetFiles(path, searchPattern);
  53
+        }
  54
+
  55
+        public override string GetFullPath(string path)
  56
+        {
  57
+            return _pathProvider.GetFullPath(path);
  58
+        }
  59
+
  60
+        public override bool IsAbsolutePath(string path)
  61
+        {
  62
+            return _pathProvider.IsAbsolutePath(path);
  63
+        }
  64
+
  65
+        public override Stream OpenInputFileStream(string path)
  66
+        {
  67
+            return _pathProvider.Open(path);
  68
+        }
  69
+
  70
+        public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share)
  71
+        {
  72
+            return _pathProvider.Open(path, mode, access, share);
  73
+        }
  74
+
  75
+        public override Stream OpenInputFileStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize)
  76
+        {
  77
+            return _pathProvider.Open(path, mode, access, share, bufferSize);
  78
+        }
  79
+
  80
+        public override Assembly LoadAssemblyFromPath(string path)
  81
+        {
  82
+            return base.LoadAssemblyFromPath(_pathProvider.MapPath(path));
  83
+        }
  84
+    }
  85
+}
83  IronRubyMvc/Core/RubyEngine.cs
@@ -26,8 +26,6 @@ namespace System.Web.Mvc.IronRuby.Core
26 26
     /// </summary>
27 27
     public class RubyEngine : IRubyEngine
28 28
     {
29  
-        private readonly Func<string, StreamContentProvider> _contentProviderFactory;
30  
-
31 29
         /// <summary>
32 30
         /// Initializes a new instance of the <see cref="RubyEngine"/> class.
33 31
         /// </summary>
@@ -37,15 +35,6 @@ public RubyEngine(ScriptRuntime runtime, IPathProvider pathProvider)
37 35
         {
38 36
             Runtime = runtime;
39 37
             PathProvider = pathProvider;
40  
-            _contentProviderFactory = path => new VirtualPathStreamContentProvider(path);
41  
-            Initialize();
42  
-        }
43  
-
44  
-        internal RubyEngine(ScriptRuntime runtime, IPathProvider pathProvider, Func<string, StreamContentProvider> contentProviderFactory)
45  
-        {
46  
-            Runtime = runtime;
47  
-            PathProvider = pathProvider;
48  
-            _contentProviderFactory = contentProviderFactory;
49 38
             Initialize();
50 39
         }
51 40
 
@@ -172,6 +161,51 @@ public object ExecuteScript(string script, ScriptScope scope)
172 161
             return Engine.Execute(script, scope ?? CurrentScope);
173 162
         }
174 163
 
  164
+        public object ExecuteFile(string path, ScriptScope scope, bool throwIfNotExist)
  165
+        {
  166
+            path.EnsureArgumentNotNull("path");
  167
+            scope.EnsureArgumentNotNull("scope");
  168
+
  169
+            if (throwIfNotExist && !PathProvider.FileExists(path)) throw new FileNotFoundException("Can't find the file", path);
  170
+            
  171
+            if(!PathProvider.FileExists(path)) return null;
  172
+
  173
+            var source = Engine.CreateScriptSourceFromFile(path); 
  174
+
  175
+            return source.Execute(scope);
  176
+        }
  177
+
  178
+        public T ExecuteFile<T>(string path)
  179
+        {
  180
+            return (T) ExecuteFile(path);
  181
+        }
  182
+
  183
+        public T ExecuteFile<T>(string path, bool throwIfNotExist)
  184
+        {