Permalink
Browse files

Fixed some issues with action name selectors

  • Loading branch information...
casualjim committed Mar 19, 2009
1 parent 0e80724 commit 38a7edd433a86dcb50c708c8986a67080ae4fd0a
@@ -91,12 +91,12 @@ protected override void EstablishContext()
requestContext);
_controllerContext = new ControllerContext(requestContext, controller);
_controllerDescriptor = new RubyControllerDescriptor(rubyClass) {RubyEngine = _rubyEngine};
_controllerDescriptor = new RubyControllerDescriptor(rubyClass, _rubyEngine);
}
protected override RubyActionDescriptor CreateSut()
{
return new RubyActionDescriptor("my_action", _controllerDescriptor);
return new RubyActionDescriptor("my_action", _controllerDescriptor, _rubyEngine);
}
protected override void Because()
@@ -134,7 +134,7 @@ protected override void EstablishContext()
protected override RubyActionDescriptor CreateSut()
{
return new RubyActionDescriptor("my_action", _controllerDescriptor);
return new RubyActionDescriptor("my_action", _controllerDescriptor, _rubyEngine);
}
protected override void Because()
@@ -42,7 +42,7 @@ protected override void EstablishContext()
protected override RubyControllerDescriptor CreateSut()
{
return new RubyControllerDescriptor(_rubyClass) { RubyEngine = _rubyEngine };
return new RubyControllerDescriptor(_rubyClass, _rubyEngine );
}
protected override void Because()
@@ -94,7 +94,7 @@ protected override void EstablishContext()
protected override RubyControllerDescriptor CreateSut()
{
return new RubyControllerDescriptor(_rubyClass) { RubyEngine = _rubyEngine };
return new RubyControllerDescriptor(_rubyClass, _rubyEngine );
}
protected override void Because()
@@ -132,7 +132,7 @@ protected override void EstablishContext()
protected override RubyControllerDescriptor CreateSut()
{
return new RubyControllerDescriptor(_rubyClass) {RubyEngine = _rubyEngine};
return new RubyControllerDescriptor(_rubyClass, _rubyEngine);
}
protected override void Because()
@@ -170,11 +170,7 @@ public void should_have_a_ruby_controller_class()
Sut.RubyControllerClass.ShouldNotBeNull();
}
[Observation]
public void should_have_a_ruby_engine()
{
Sut.RubyEngine.ShouldNotBeNull();
}
[Observation]
public void should_have_the_correct_ruby_controller_class()
@@ -85,9 +85,7 @@
</Reference>
<Reference Include="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
<Reference Include="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\dependencies\System.Web.Routing.dll</HintPath>
<Reference Include="System.Web.Routing">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml" />
@@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Web.Hosting;
using Microsoft.Scripting;
#endregion
View
@@ -10,7 +10,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
ProjectSection(SolutionItems) = preProject
IronRubyMvcKey.public = IronRubyMvcKey.public
IronRubyMvcKey.snk = IronRubyMvcKey.snk
README = README
README.markdown = README.markdown
EndProjectSection
EndProject
Global
@@ -50,4 +50,3 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -1,5 +1,6 @@
#region Usings
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc.IronRuby.Core;
@@ -26,7 +27,6 @@ public RubyActionMethodSelector(IRubyEngine rubyEngine, RubyClass rubyClass)
{
ControllerClass = rubyClass;
_rubyEngine = rubyEngine;
}
public RubyClass ControllerClass { get; set; }
@@ -35,7 +35,7 @@ public RubyActionMethodSelector(IRubyEngine rubyEngine, RubyClass rubyClass)
/// Gets or sets the aliased methods.
/// </summary>
/// <value>The aliased methods.</value>
public IEnumerable<KeyValuePair<string, Func<string, bool>>> AliasedMethods { get; private set; }
public IEnumerable<KeyValuePair<string, PredicateList>> AliasedMethods { get; private set; }
/// <summary>
/// Gets or sets the non aliased method names.
@@ -56,9 +56,9 @@ private void PopulateLookupTables(IEnumerable<string> methodNames)
NonAliasedMethods = methodNames.Where(method => AliasedMethods.DoesNotContain(pair => String.Equals(pair.Key, method, StringComparison.OrdinalIgnoreCase)));
}
private KeyValuePair<string, Func<string, bool>> KeyValuePairFor(KeyValuePair<object, object> pair)
private KeyValuePair<string, PredicateList> KeyValuePairFor(KeyValuePair<object, object> pair)
{
return new KeyValuePair<string, Func<string, bool>>(pair.Key.ToString(), _rubyEngine.ConvertProcToFunc<bool>((Proc) pair.Value));
return new KeyValuePair<string, PredicateList>(pair.Key.ToString(), new PredicateList(_rubyEngine, (RubyArray) pair.Value));
}
private static AmbiguousMatchException CreateAmbiguousMatchException(string actionName)
@@ -69,7 +69,7 @@ private static AmbiguousMatchException CreateAmbiguousMatchException(string acti
public string FindActionMethod(ControllerContext controllerContext, string actionName)
{
PopulateLookupTables(controllerContext); // dynamic languages can add methods at runtime
var methodsMatchingName = GetMatchingAliasedMethods(actionName);
var methodsMatchingName = GetMatchingAliasedMethods(controllerContext, actionName);
methodsMatchingName.AddRange(NonAliasedMethods.Where(name => String.Equals(name, actionName, StringComparison.OrdinalIgnoreCase)));
var finalMethods = RunSelectionFilters(controllerContext, methodsMatchingName);
@@ -96,19 +96,80 @@ public IEnumerable<string> GetAllActionMethods()
return result;
}
private List<string> GetMatchingAliasedMethods(string actionName)
private List<string> GetMatchingAliasedMethods(ControllerContext controllerContext, string actionName)
{
return new List<string>(AliasedMethods.Where(pair => pair.Value(actionName)).Map(pair => pair.Key));
return new List<string>(AliasedMethods.Where(pair => pair.Key == actionName && pair.Value.IsValidForName(controllerContext, actionName)).Map(pair => pair.Key));
}
private List<string> RunSelectionFilters(ControllerContext controllerContext, IEnumerable<string> matchingMethods)
{
var filtersDescriptions = (Hash) _rubyEngine.CallMethod(controllerContext.Controller, "method_selectors");
var filters = filtersDescriptions.Map(pair => _rubyEngine.ConvertProcToFunc<bool>((Proc) pair.Value));
return filters.Count() == 0
? new List<string>(matchingMethods)
: new List<string>(matchingMethods.Where(methodName => filters.All(filter => filter(methodName))));
var filtersDescriptions = (Hash) _rubyEngine.CallMethod(ControllerClass, "method_selectors");
var filters = filtersDescriptions.Where(pair => matchingMethods.Contains(pair.Key.ToString())).Map(pair => KeyValuePairFor(pair));
return filters.Count() == 0
? new List<string>(matchingMethods)
: new List<string>(
matchingMethods.Where(
methodName => filters.All(filter => filter.Value.IsValidForName(controllerContext, methodName))
)
);
}
}
public class PredicateList : IEnumerable<Func<ControllerContext, string, bool>>
{
private readonly RubyArray _items;
private readonly List<Func<ControllerContext, string, bool>> _predicates = new List<Func<ControllerContext, string, bool>>();
private readonly IRubyEngine _rubyEngine;
public PredicateList(IRubyEngine rubyEngine, RubyArray items)
{
_rubyEngine = rubyEngine;
_items = items;
Populate();
}
private void Populate()
{
_items.ForEach(obj => Add((Proc) obj));
}
private void Add(Proc proc)
{
_predicates.Add(_rubyEngine.ConvertProcToFunc<bool>(proc));
}
public bool IsValidForName(ControllerContext context, string name)
{
return _predicates.All(predicate => predicate(context, name));
}
#region Implementation of IEnumerable
/// <summary>
/// Returns an enumerator that iterates through the collection.
/// </summary>
/// <returns>
/// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>1</filterpriority>
public IEnumerator<Func<ControllerContext, string, bool>> GetEnumerator()
{
return _predicates.GetEnumerator();
}
/// <summary>
/// Returns an enumerator that iterates through a collection.
/// </summary>
/// <returns>
/// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
/// </returns>
/// <filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
}
}
@@ -160,16 +160,16 @@ def method_selector(name, selector)
end
def alias_action(name, act_name)
fn = lambda do |controller_context, action_name|
fn = Proc.new do |controller_context, action_name|
!!/#{action_name.to_s}/i.match(act_name.to_s)
end
name_selector(name, fn)
end
def name_selector(name, &selector)
def name_selector(name, selector=nil, &b)
key = name.to_s.to_sym
name_selectors[key] ||= []
name_selectors[key] << selector
name_selectors[key] << (selector||b)
name_selectors[key].uniq!
name_selectors[key]
end
@@ -35,7 +35,7 @@ public interface IRubyEngine
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="proc">The proc.</param>
/// <returns></returns>
Func<string, TResult> ConvertProcToFunc<TResult>(Proc proc);
Func<ControllerContext, string, TResult> ConvertProcToFunc<TResult>(Proc proc);
/// <summary>
/// Calls the method.
@@ -132,9 +132,9 @@ public RubyController ConfigureController(RubyClass rubyClass, RequestContext re
/// <typeparam name="TResult">The type of the result.</typeparam>
/// <param name="proc">The proc.</param>
/// <returns></returns>
public Func<string, TResult> ConvertProcToFunc<TResult>(Proc proc)
public Func<ControllerContext, string, TResult> ConvertProcToFunc<TResult>(Proc proc)
{
return name => (TResult) proc.Call(name);
return (context, name) => (TResult) proc.Call(context, name);
}
public string GetMethodName(object receiver, string message)
@@ -41,6 +41,18 @@ public static void ForEach(this IDictionary dictionary, Action<object, object> i
}
}
internal static FilterInfo ToFilterInfo(this IDictionary<object, object> filterDescriptions, string actionName)
{
var filterInfo = new FilterInfo();
filterDescriptions.ToActionFilters(actionName).ForEach(filter => filterInfo.ActionFilters.Add(filter));
filterDescriptions.ToAuthorizationFilters(actionName).ForEach(filter => filterInfo.AuthorizationFilters.Add(filter));
filterDescriptions.ToExceptionFilters(actionName).ForEach(filter => filterInfo.ExceptionFilters.Add(filter));
filterDescriptions.ToResultFilters(actionName).ForEach(filter => filterInfo.ResultFilters.Add(filter));
return filterInfo;
}
private static IEnumerable<TITarget> ToFilters<TITarget>(this IDictionary<object, object> filterDescriptions, string actionName)
where TITarget : class
{
@@ -82,7 +82,7 @@ public static bool DoesNotContain<TSource>(this IEnumerable<TSource> collection,
return true;
}
public static bool Contains(this IEnumerable collection, Func<object, bool> predicate)
public static bool Contains(this IEnumerable collection, Predicate<object> predicate)
{
foreach (var o in collection)
{
@@ -100,43 +100,51 @@ public static bool Contains(this IEnumerable collection, object value)
return false;
}
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> collection, Func<TSource, bool> predicate)
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> collection, Predicate<TSource> predicate)
{
foreach (var source in collection)
{
if (predicate(source)) yield return source;
}
}
public static bool All<TSource>(this IEnumerable<TSource> collection, Func<TSource, bool> predicate)
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> collection, Predicate<TSource> predicate)
{
foreach (var source in collection)
{
if(!predicate(source)) return false;
if(predicate(source)) return source;
}
return true;
return default(TSource);
}
public static IEnumerable Where(this IEnumerable collection, Func<object, bool> predicate)
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> collection)
{
foreach (var source in collection)
{
if (predicate(source)) yield return source;
return source;
}
return default(TSource);
}
internal static FilterInfo ToFilterInfo(this IDictionary<object, object> filterDescriptions, string actionName)
public static bool All<TSource>(this IEnumerable<TSource> collection, Predicate<TSource> predicate)
{
var filterInfo = new FilterInfo();
filterDescriptions.ToActionFilters(actionName).ForEach(filter => filterInfo.ActionFilters.Add(filter));
filterDescriptions.ToAuthorizationFilters(actionName).ForEach(filter => filterInfo.AuthorizationFilters.Add(filter));
filterDescriptions.ToExceptionFilters(actionName).ForEach(filter => filterInfo.ExceptionFilters.Add(filter));
filterDescriptions.ToResultFilters(actionName).ForEach(filter => filterInfo.ResultFilters.Add(filter));
foreach (var source in collection)
{
if(!predicate(source)) return false;
}
return true;
}
return filterInfo;
public static IEnumerable Where(this IEnumerable collection, Predicate<object> predicate)
{
foreach (var source in collection)
{
if (predicate(source)) yield return source;
}
}
internal static IEnumerable<TTarget> Cast<TTarget>(this IEnumerable collection) where TTarget : class
{
var result = new List<TTarget>();
@@ -174,6 +182,16 @@ internal static int Count(this IEnumerable collection)
return count;
}
internal static int Count<TSource>(this IEnumerable<TSource> collection, Predicate<TSource> predicate)
{
var count = 0;
foreach (var o in collection)
{
if(predicate(o)) count++;
}
return count;
}
internal static TSource[] ToArray<TSource>(this IEnumerable<TSource> collection)
{
var result = new TSource[collection.Count()];
Oops, something went wrong.

0 comments on commit 38a7edd

Please sign in to comment.