I'm trying to use the built-in laravel's Ioc container to inject a PageManager class inside a Page model and I'm a little lost.
What I'm trying to achieve is something like that:
class Pages extends Eloquent {
public function __construct(PagesManagerInterface $manager, array $attributes = array())
{
parent::__construct($attributes);
$this->manager = new $manager;
}
public function saveToDisk()
{
$this->manager->writeToFile();
}
But I obtain this error:
ErrorException: Argument 1 passed to Pages::__construct() must be an instance of PagesManagerInterface, none given.
I tried to add this in app/start/global.php:
App::bind('Pages',function(){
return new Pages(new PagesManager);
});
But is seems ignored by the framework, and also i don't know how to insert the $attribute array into this declaration.
I'm a little lost so any help is appreciated!
It's not a good idea to overload a model's constructor because new instances can be spawned behind the scenes through various methods, like Model::find().
When that happens, the dependencies you're asking for in your custom constructor aren't being passed in because the Model class isn't aware of them. So, you get that error message.
See the find() method here: http://laravel.com/api/source-class-Illuminate.Database.Eloquent.Model.html#380-397
See this post by Jason Lewis: http://forums.laravel.io/viewtopic.php?pid=47124#p47124
I think that what you need is:
App::bind('PagesManagerInterface',function(){
return new Pages(new PagesManager);
});
This tells Laravel to inject a new Page object everytime it needs an instance of your PagesManagerInterface wich wasn't passed while creating the model.
In Laravel you can use the IoC Container:
public function saveToDisk(){
$managerObject = app()->make('path\to\class\PagesManagerInterface');
$managerObject->writeToFile();
}
Related
I have the following code structure which I want to compose with Ninject:
ICommandHandler<FindAssetById, Asset> handler =
new SecurityCommandHandlerDecorator<FindAssetById, Asset>(
new SecurityValidatorComposite<FindAssetById>(
// This list contains both non-generic as generic implementations
new ISecurityValidator<FindAssetById>[]
{
// Contains type constraint 'where T : IRequireAccessToAsset'
new RequireAccessToAssetSecurityValidator<FindAssetById>(...)
}),
new FindAssetByIdHandler(...));
I have this setup in my Ninject:
//Bind Composite To Handler
_kernel.Bind(typeof(ISecurityValidator<>))
.To(typeof(SecurityValidatorComposite<>))
.WhenInjectedInto(typeof(SecurityCommandHandlerDecorator<,>));
//Bind Interface To Concrete
_kernel.Bind(typeof(ISecurityValidator<>))
.To(typeof(RequireAccessToAssetSecurityValidator<>))
.WhenInjectedInto(typeof(SecurityValidatorComposite<>));
_kernel.Bind(typeof(ISecurityValidator<>))
.To(typeof(RequireAccessToSecureAssetSecurityValidator<>))
.WhenInjectedInto(typeof(SecurityValidatorComposite<>));
I want to be able to conditionally bind the concrete validators if the calling parent implements the corresponding interface.
For instance a class like this:
public class FindAssetById: IRequireAccessToAsset{
}
Should get the RequireAccessToAssetSecurityValidator but not the RequireAccessToSecureAssetSecurityValidator. With Ninject the current way it is setup it obviously gets both. But with Ninject you can't call WhenInjectedInto and a conditional When statement. With how difficult this has been I'm assuming at this point I am way off base and how to implement and any suggestions to fix this would be very helpful.
In Simple Injector the equivalent would be something like this:
container.Register(
typeof(ISecurityValidator<>),
typeof(SecurityValidatorComposite<>),
Lifestyle.Singleton);
container.Collection.Register(typeof(ISecurityValidator<>), assemblies);
container.Collection.Append(typeof(ISecurityValidator<>),
typeof(RequireAccessToAssetSecurityValidator<>));
And somehow it knows to apply the right one or the example provided is incomplete. I'd like to replicate something like this with Ninject as I think the solution from here is fairly clean and where I got most of my code from https://github.com/dotnetjunkie/solidservices/issues/4. This is my first foray into really trying to understand DI and how I can apply the decorator pattern with it so any help would be greatly appreciated.
I'm trying to pass Param data from view to controller and I'm having trouble. Here's what I'm currently trying to do.
View:
<form action="${doStuffURL}" method='post' params="[keyId: ${mykey.id[i]}]"><g:actionSubmit value="doStuff"/></form>
Controller:
def myObjectService //inject service object
def doStuff = {
myObjectService.doStuff("${params.keyId}") //this blows up because it's value of NULL
myObjectService.doStuff(8) //this works fine
}
It gets to the method block because the error log says "no signature of method MyObject.doStuff() is applicable for argument types: values: [null]." Also, I'm able to see ${mykey.id[i]} data from another field, so the data is definitely in the view.
How can I get the controller to read the Param data?
Thanks!
err lots wrong here:
<form action="${doStuffURL}" method='post' params="[keyId: ${mykey.id[i]}]"><g:actionSubmit value="doStuff"/></form>
why not use:
<g:form name="something" controller="yourController" action="youraction">
As you can see above you are having to generate
form url (maybe you have your reasons)
Controller:
def doStuff = {
MyObject.doStuff("${params.keyId}")
}
Differences between action and methods in Grails controllers
So firstly why you should change controller but my actual concern here is
MyObject.doStuff
is MyObject.doStuff a static method ?
since that is only when a call like this would work. The link shows a static method. gets called here and it may confuse you due to it calling it via executor.registerSenderFault due to how it is generated working - expandability - for future classes that do same thing. this could have been EmailExecutor.registerSenderFault which is the full class in uppercase like you have declared.
surely it should be a service notice starting with lower case.
myObjectServive.doStuff(stuff)
If above is some real method in MyObject and is not a static method then you need to instantiate the class
MyObject myObject = new MyObject()
myObject.doStuff(stuff)
but in short this is why services exist it is all there to save you all the hassle since they just get injected.
I suggest you do some reading looking around
E2A
def doStuff = {
println "my params are $params "
//do you see keyId in there ?
//if so what is doStuff expecting as input a string ?:
// since if you do
println "${params.keyId.getClass()}"
//by default it will be a string you may need to change it from:
//myObjectService.doStuff("${params.keyId}")
myObjectService.doStuff(params.keyId as Long)
}
Personally I don't think it is any of the above edited comments, it still relates to how/what you are injecting. I have seen similar issues. I would suggest you create a brand new service and inject new service as a test and start again - not convinced you were injecting it correctly or if you are the service may be some abstract class rather than a normal service. Or.... you are making some form of similar mistake in the uppercase/lowercase declaration of the service name so you may have created:
MyObjectnameService and calling it using myObjectNameService difference in N in those or.... even worse you have created actual service as myObjectNameService with lowercase name.
test this all again using a much simpler naming convention and create a new service as a test
grails create service MyService
and try again using this service
I've been struggling for a while reading and trying to understand command objects, but I've yet to understand how to use them in my particular scenario.
Here's what I have:
class Beneficary {
String name
//more attributes
static hasMany = [dependents = Dependent]
}
class Dependent {
DegreeKinship degreeKinship //enum
//several atrributes
static belongsTo = [beneficiary: Beneficiary]
}
I've read in several articles, including SO answers, that one should be using Command Objects for this if one wishes but I'm failing to understand just how.
I've wrote this:
class DependentCommand {
List<Dependent> dependents = ListUtils.lazyList([], {new Dependent()} as Factory)
}
but I'm not sure how to use it in my Beneficiary class.
Also, I wish to have it all under a single view (beneficiary/create)
Any help would be greatly appreciated.
I don't think you should use them in the Beneficary class, use them in BeneficaryController.
Command objects give you a standardized way of encapsulating, converting and validating request parameters. As such the main use for them is in a controller, not a domain class which can already do most of a command object's functions natively.
You could rewrite your command like this if you wanted to accept a request containing parameters along the lines of dependents=1&dependents=2:
class DependentCommand {
List<Dependent> dependents
}
Suppose i have a repository that returns a list of Posts. The repository interface has a GetAll() method which does what it suggests.
Now in keeping with the theory that i shouldn't be putting domain logic in the repository, i want to intercept calls to the concrete GetAll() method such that i can add the following logic to the GetAll() result:
return GetAll().OrderByDescending(p => p.Posted).ToList();
The reason i want to intercept this is because (1) i don't want to have the client remember to call an extension method (OrderByDescending or some useless wrapper of that), i want it called every time and (2) i don't want to have all my concrete implementations have to remember to order the GetAll() result - i want this logic in a single place external to any repository.
What's the easiest way to do this?
I'm already using StructureMap so if i can intercept with this it might be a low cost option. But i don't think SM intercepts method calls, just the creation of the object instance?
Do i need to go to a proxy or mixin pattern? Do i need to go all-in with Castle Dynamic Proxy? Or is there another method i should consider or perhaps a combination?
I'm really interested in a concrete suggestion to my particular example above. I'm novice to AOP so please be gentle.
Went with the DynamicProxy option. It was easier to use than i thought.
All it took was the using Castle.DynamicProxy; reference...
A bit of IInterceptor...
public class PostRepoInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
if (invocation.Method.Name.Equals("GetAll", StringComparison.InvariantCultureIgnoreCase))
invocation.ReturnValue = this.GetModifiedGetAllResult(invocation.ReturnValue);
}
private object GetModifiedGetAllResult(object getAllResult)
{
return Post.GetOrderedPosts((IList<Post>)getAllResult);
}
}
Two new lines in StructureMap config:
public RepoRegistry()
{
var pg = new ProxyGenerator();
For<IPostRepository>()
.EnrichAllWith(z => pg.CreateInterfaceProxyWithTarget<IPostRepository>(z, new PostRepoInterceptor()));
}
..and it's done. GetAll() now behaves how i want. I can still use the interfaces the way i'm familar and i've kept it all DRY and decoupled for DDD.
Thanks to Sam and Andre.
AFAIK, StructureMap only intercepts object construction, so using it it's not going to work.
I don't know Castle, but I think that the idea - here - is to apply Decorator pattern, so you could also do it by yourself without recurring to a third party library by following the steps described in the previous link.
That's how I'd do it, since I'm not a big fan of AOP.
HTH
No, it can not change the return value. However, you can access the target inside aspect to change target's property. Assuming you has already Repository defined, here is the code to add post processing aspect to change target property.
IRepository<decimal> Rep = new Repository();
IRepository<decimal> tpRep = (IRepository<decimal>)ObjectProxyFactory.CreateProxy(Rep,
new String[] { "GetAll" },
null,
new Decoration((x, y) =>
{
Console.WriteLine("Entering " + x.GetType().ToString());
if (x.GetType().ToString() == "ThirdPartyHR.Repository")
{
List<decimal> decimals = ((Repository)x).RepList;
IEnumerable<decimal> query = decimals.OrderByDescending(num => num, new SpecialComparer()).ToList<decimal>();
((Repository)x).RepList = (List<decimal>)query;
}
}, null));
tpRep.GetAll();
List<decimal> lstRep = Rep.RepList;
If needed, I can send you complete working code. And, if possible, please reply to me from the article "Add Aspects to Object Using Dynamic Decorator" since I don't automatically get the message here.
There is an article Add Aspects to Object Using Dynamic Decorator.
It describes an approach to adding aspects to object at runtime instead of adding aspects to class at design time. Looks like that is what you want.
I've added some functionality to some of my instance classes in my symfony project that I want ALL of my instance classes to have. If I didn't have any qualms about editing the core symfony installation, I would just add my methods directly to the sfDoctrineRecord class. But I don't want to do that, of course, because my changes would break on upgrade, plus my changes wouldn't port well to other projects.
If I want to add certain functionality to all my instance classes in symfony, what's the "right" way to do that?
(P.S. When I say "instance class", I mean something like lib/model/doctrine/Customer.class.php.)
Steps:
Create myDoctrineRecord
abstract class myDoctrineRecord extends sfDoctrineRecord
{
public function commonRecordMethod() { }
}
I place this file in lib/record, but you can put it anywhere that the autoloader will see it.
Set Symfony to use this class in the configureDoctrine callback of your ProjectConfiguration:
public function configureDoctrine(Doctrine_Manager $manager)
{
sfConfig::set('doctrine_model_builder_options', array('baseClassName' => 'myDoctrineRecord'));
}
That's it! Isn't Symfony great? :)
I suppose the proper way would probably be to add a Doctrine_Template to the models in question, however you would need to define it as a behavior for every model in your schema.yml
class MyMethodsTemplate extends Doctrine_Template
{
public function customMethod1(){
$model = $this->getInvoker();
//do stuff with model
}
public function customMethod2(){
$model = $this->getInvoker();
//do stuff with model
}
}
And then in your schema.yml:
ModelName:
actAs:
MyMethodTemplate: ~
# the rest of your definition
After you rebuild you should be able to call:
$model = new ModelName();
$model->customMethod1();
$model->customMethod2();
Of course Doctrine templates and listeners are much more powerful than that. You should take a look at the documentation for decent overview