- Fixed MR-84
[castle.git] / MonoRail / Castle.MonoRail.ActiveRecordSupport / ARFetchAttribute.cs
blob9eb1a4852ee5d6c2d125db413f48e2e43ac757d5
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.ActiveRecordSupport
17 using System;
18 using System.Reflection;
20 using Castle.MonoRail.Framework;
22 /// <summary>
23 /// Mark a parameter with this attribute to instruct the <see cref="SmartDispatcherController" />
24 /// to load an <c>ActiveRecord</c> instance of the parameter type, using the request parameter
25 /// as the identifier.
26 /// </summary>
27 /// <remarks>
28 /// The <see cref="ARFetchAttribute"/> only loads an instance
29 /// based on the primary key value obtained from <see cref="IRailsEngineContext.Params"/>
30 /// <para>For example:</para>
31 /// <code>
32 /// public class CustomerController : ARSmartDispatcherController
33 /// {
34 /// public void UpdateCustomerLocation([ARFetch("customer.id")] Customer customer, [ARFetch("location.id")] Location location)
35 /// {
36 /// customer.Location = location;
37 /// customer.Save();
38 ///
39 /// RedirectToAction("index");
40 /// }
41 /// }
42 /// </code>
43 /// The code above assumes that you have the fields
44 /// <c>customer.id</c> and <c>location.id</c> on the form being
45 /// submitted.
46 /// </remarks>
47 [AttributeUsage(AttributeTargets.Parameter), Serializable]
48 public class ARFetchAttribute : Attribute, IParameterBinder
50 private String requestParameterName;
51 private bool create, required;
52 private String eager;
54 /// <summary>
55 /// Constructs an <see cref="ARFetchAttribute"/>
56 /// specifying the parameter name and the create and require behavior
57 /// </summary>
58 /// <param name="requestParameterName">The parameter name to be read from the request</param>
59 /// <param name="create"><c>true</c> if you want an instance even when the record is not found</param>
60 /// <param name="required"><c>true</c> if you want an exception if the record is not found</param>
61 public ARFetchAttribute(String requestParameterName, bool create, bool required) : base()
63 this.requestParameterName = requestParameterName;
64 this.create = create;
65 this.required = required;
68 /// <summary>
69 /// Constructs an <see cref="ARFetchAttribute"/> using the
70 /// parameter name as the <see cref="ARFetchAttribute.RequestParameterName"/>
71 /// </summary>
72 public ARFetchAttribute() : this(null, false, false)
76 /// <summary>
77 /// Constructs an <see cref="ARFetchAttribute"/> specifing the
78 /// parameter name
79 /// <seealso cref="ARFetchAttribute.RequestParameterName"/>
80 /// </summary>
81 public ARFetchAttribute(String requestParameterName) : this(requestParameterName, false, false)
85 /// <summary>
86 /// Constructs an <see cref="ARFetchAttribute"/> using the
87 /// parameter name as the <see cref="ARFetchAttribute.RequestParameterName"/>
88 /// and the create and require behavior
89 /// </summary>
90 /// <param name="create"><c>true</c> if you want an instance even when the record is not found</param>
91 /// <param name="require"><c>true</c> if you want an exception if the record is not found</param>
92 public ARFetchAttribute(bool create, bool require) : this(null, create, require)
96 /// <summary>
97 /// The parameter name to be read from the request. The parameter value will
98 /// be used as the primary key value to load the target object instance.
99 /// </summary>
100 public String RequestParameterName
102 get { return requestParameterName; }
103 set { requestParameterName = value; }
106 /// <summary>
107 /// When set to <c>true</c> an instance of
108 /// the target type will be created if the record
109 /// is not found. The default is <c>false</c>.
110 /// </summary>
111 public bool Create
113 get { return create; }
114 set { create = value; }
117 /// <summary>
118 /// When set to <c>true</c>, an exception will be thrown
119 /// if the record specified is not found. The default is <c>false</c>.
120 /// </summary>
121 public bool Required
123 get { return required; }
124 set { required = value; }
127 /// <summary>
128 /// Comma-separated list of lazy associations to eager-fetch, when loading the ActiveRecord object.
129 /// </summary>
130 public String Eager
132 get { return eager; }
133 set { eager = value; }
136 public virtual int CalculateParamPoints(SmartDispatcherController controller, ParameterInfo parameterInfo)
138 String paramName = RequestParameterName != null ? RequestParameterName : parameterInfo.Name;
140 return controller.Request.Params.Get(paramName) != null ? 10 : 0;
143 public virtual object Bind(SmartDispatcherController controller, ParameterInfo parameterInfo)
145 ARFetcher fetcher = new ARFetcher(controller.Binder.Converter);
147 return fetcher.FetchActiveRecord(parameterInfo, this, controller.Request);