Skip to content

Commit

Permalink
Basic support for action filters is close :)
Browse files Browse the repository at this point in the history
Signed-off-by: Jimmy Schementi <jschementi@gmail.com>
  • Loading branch information
casualjim authored and jschementi committed Mar 2, 2009
1 parent a6a4e14 commit 4f606c0
Show file tree
Hide file tree
Showing 21 changed files with 510 additions and 126 deletions.
13 changes: 0 additions & 13 deletions IronRubyMvc.Tests/Controllers/AfterActionFilter.cs

This file was deleted.

7 changes: 0 additions & 7 deletions IronRubyMvc.Tests/Controllers/AroundActionFilter.cs

This file was deleted.

14 changes: 0 additions & 14 deletions IronRubyMvc.Tests/Controllers/BeforeActionFilter.cs

This file was deleted.

35 changes: 23 additions & 12 deletions IronRubyMvc.Tests/Controllers/DelegateActionFilter.cs
Expand Up @@ -8,28 +8,39 @@

namespace IronRubyMvcLibrary.Tests.Controllers
{
public abstract class DelegateActionFilter : IActionFilter
{
private readonly Action<ActionExecutedContext> _onActionExecuted;
private readonly Action<ActionExecutingContext> _onActionExecuting;


protected DelegateActionFilter(Action<ActionExecutingContext> onActionExecuting,
Action<ActionExecutedContext> onActionExecuted)
{
_onActionExecuting = onActionExecuting;
_onActionExecuted = onActionExecuted;
}
public abstract class DelegateActionFilter : IActionFilter, IResultFilter
{
public Action<ActionExecutingContext> BeforeAction { get; set; }
public Action<ActionExecutedContext> AfterAction { get; set; }
public Action<ResultExecutingContext> BeforeResult { get; set; }
public Action<ResultExecutedContext> AfterResult { get; set; }

#region IActionFilter Members

public virtual void OnActionExecuting(ActionExecutingContext filterContext)
{
if(_onActionExecuting.IsNotNull()) _onActionExecuting(filterContext);
if(BeforeAction.IsNotNull()) BeforeAction(filterContext);
}

public virtual void OnActionExecuted(ActionExecutedContext filterContext)
{
if(_onActionExecuted.IsNotNull()) _onActionExecuted(filterContext);
if(AfterAction.IsNotNull()) AfterAction(filterContext);
}

#endregion

#region Implementation of IResultFilter

public virtual void OnResultExecuting(ResultExecutingContext filterContext)
{
if (BeforeResult.IsNotNull()) BeforeResult(filterContext);
}

public virtual void OnResultExecuted(ResultExecutedContext filterContext)
{
if (AfterResult.IsNotNull()) AfterResult(filterContext);
}

#endregion
Expand Down
7 changes: 0 additions & 7 deletions IronRubyMvc.Tests/Controllers/DelegateResultFilter.cs

This file was deleted.

7 changes: 0 additions & 7 deletions IronRubyMvc.Tests/Controllers/ResultFilter.cs

This file was deleted.

1 change: 1 addition & 0 deletions IronRubyMvc.Tests/IronRubyMvcLibrary.Tests.csproj
Expand Up @@ -95,6 +95,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Controllers\DelegateActionFilter.cs" />
<Compile Include="Controllers\RubyActionDescriptorFixture.cs" />
<Compile Include="Controllers\RubyControllerActionInvokerSpec.cs" />
<Compile Include="Controllers\RubyControllerDescriptorSpec.cs" />
Expand Down
73 changes: 73 additions & 0 deletions IronRubyMvc/Controllers/HashToActionFilterConverter.cs
@@ -0,0 +1,73 @@
using System.Collections;
using System.Collections.Generic;
using System.IO;
using IronRuby.Builtins;
using IronRubyMvcLibrary.Core;
using IronRubyMvcLibrary.Extensions;
using Microsoft.Scripting;

namespace IronRubyMvcLibrary.Controllers
{
public interface IConverter<TTarget>
{
TTarget Convert();
}
public class HashToActionFilterConverter : IConverter<RubyActionFilter>
{
private readonly Hash _filterDescription;

private static readonly IEnumerable<SymbolId> _actionFilterDenominators = new[]
{
SymbolTable.StringToId("before"),
SymbolTable.StringToId("after"),
SymbolTable.StringToId("around"),
SymbolTable.StringToId("before_result"),
SymbolTable.StringToId("after_result")
};

private static readonly IDictionary<When, SymbolId> _actionWhen = new Dictionary<When, SymbolId>
{
{When.BeforeAction, SymbolTable.StringToId("before")},
{When.AfterAction, SymbolTable.StringToId("after")},
{When.BeforeResult, SymbolTable.StringToId("before_result")},
{When.AfterResult, SymbolTable.StringToId("after_result")},

};

private static readonly SymbolId whenKey = SymbolTable.StringToId("when");

public HashToActionFilterConverter(Hash filterDescription)
{
_filterDescription = filterDescription;
}

#region Implementation of IConverter<RubyActionFilter>

public RubyActionFilter Convert()
{
if (!IsActionFilter(_filterDescription))
throw new InvalidDataException("The filter description is invalid.");

return new RubyActionFilter
{
BeforeAction = FindProc(_filterDescription, _actionWhen[When.BeforeAction]),
AfterAction = FindProc(_filterDescription, _actionWhen[When.AfterAction]),
BeforeResult = FindProc(_filterDescription, _actionWhen[When.BeforeResult]),
AfterResult = FindProc(_filterDescription, _actionWhen[When.AfterResult])
};
}

#endregion

private static bool IsActionFilter(IDictionary<object, object> hash)
{
var key = (SymbolId)hash[whenKey];
return _actionFilterDenominators.Contains(key);
}

private static Proc FindProc(IDictionary<object, object> hash, SymbolId key)
{
return hash.ContainsKey(key) ? (Proc)hash[key] : null;
}
}
}
89 changes: 89 additions & 0 deletions IronRubyMvc/Controllers/RubyActionFilter.cs
@@ -0,0 +1,89 @@
#region Usings

using System.Collections.Generic;
using System.Web.Mvc;
using IronRuby.Builtins;
using IronRubyMvcLibrary.Core;
using IronRubyMvcLibrary.Extensions;

#endregion

namespace IronRubyMvcLibrary.Controllers
{
/// <summary>
/// Implements <see cref="IActionFilter"/> and <see cref="IResultFilter"/>
/// This class hooks the ruby defined filters with
/// </summary>
public class RubyActionFilter : IActionFilter, IResultFilter
{
public IEnumerable<string> OnlyForActions { get; set; }
public IEnumerable<string> ExceptForActions { get; set; }
public Proc BeforeAction { get; set; }
public Proc AfterAction { get; set; }
public Proc BeforeResult { get; set; }
public Proc AfterResult { get; set; }
public When FilterType { get; set; }

#region Implementation of IActionFilter

/// <summary>
/// Called before the action executes
/// </summary>
/// <param name="filterContext">The filter context.</param>
public void OnActionExecuting(ActionExecutingContext filterContext)
{
if (BeforeAction.IsNotNull() && CanExecute(filterContext))
BeforeAction.Call(filterContext);
}

/// <summary>
/// Called after an action executed
/// </summary>
/// <param name="filterContext">The filter context.</param>
public void OnActionExecuted(ActionExecutedContext filterContext)
{
if ( AfterAction.IsNotNull() && CanExecute(filterContext))
AfterAction.Call(filterContext);
}

#endregion

#region Implementation of IResultFilter

public void OnResultExecuting(ResultExecutingContext filterContext)
{
if (BeforeResult.IsNotNull())
BeforeResult.Call(filterContext);
}

public void OnResultExecuted(ResultExecutedContext filterContext)
{
if (AfterResult.IsNotNull())
AfterResult.Call(filterContext);
}

#endregion

#region Implementation of IRubyControllerFilter

private bool CanExecute(ActionExecutingContext context)
{
var actionName = context.ActionDescriptor.ActionName;
return CanExecute(actionName);
}

private bool CanExecute(ActionExecutedContext context)
{
var actionName = context.ActionDescriptor.ActionName;
return CanExecute(actionName);
}

private bool CanExecute(string actionName)
{
return OnlyForActions.IsEmpty() || OnlyForActions.Contains(actionName)
|| ExceptForActions.IsEmpty() || ExceptForActions.DoesNotContain(actionName);
}

#endregion
}
}
4 changes: 0 additions & 4 deletions IronRubyMvc/Controllers/RubyController.cs
Expand Up @@ -31,10 +31,6 @@ public class RubyController : Controller
public string ControllerName { get; internal set; }
public RubyClass RubyType { get; private set; }

// public static Hash ActionFilters { get; set; }
//
// public static Hash ActionResult { get; set; }

public string ControllerClassName
{
get { return Constants.CONTROLLERCLASS_FORMAT.FormattedWith(ControllerName); }
Expand Down

0 comments on commit 4f606c0

Please sign in to comment.