We use the following general pattern with Grails controllers and command objects
SomeController {
def someAction() {
SomeCommandObject co = SomeCommandObject.valueOf(params)
if(!co.validate()) {
// return bad request
}
someService.doWork(co)
// return ok
}
SomeService {
def doWork(SomeCommandObject co) {
notTrue(!co.hasErrors(), 'cant have errors') // Commons validation
// do actual work
}
}
Apparently, if co.validate() has not been called, .hasErrors() will always return false. Is there a better way to enforce that .validate() has been called before a command object is passed between application layers? We don't want to pass around invalid command objects but we don't want to force every new method to re-validate the command object either.
Note: We aren't using the default controller/command object creation pattern because we need to do some custom parameter map checking, we use a static valueOf method instead to create the command object. Answers that change that practice are also welcome.
EDIT: A little more info on why we aren't using the 'default' controller/command object creation. Specifically why we aren't doing ..
def someAction(SomeCommandObject co) {
}
We have a requirement to disallow random query parameters, eg. endpoint/object?color=blue. To do that we need access to the parameter map in the command object to verify that it doesn't contain any 'unexpected' parameter keys. As I understand it, the default way would just create a member on the CO named color, and I don't see how to prevent arbitrary members using even custom validators. I'd happily entertain suggestions for doing so, thereby allowing us to use this default means.
Yes; what you can do is pass the command object as a parameter to the controller, and then the command will always be validated automatically.
Also, what you can do, is to make a filter or similar, so that you don't have to check for the hasErrors() each time, but handle all the cases in the same way (for example, by throwing an error, or returning with a specific response).
In an application we created, we had something like:
withValidCommand(cmd) {
// do work
}
Which worked pretty well. But maybe you can come up something even more elegant.
You should be doing this:
def someAction(SomeCommandObject co) {
if (!co.hasErrors()) {
someService.doWork(co)
}
}
By passing SomeCommandObject in as the argument grails will automatically populate it from params and validate. No need to do it manually.
Related
I'm new to OOP and Yii2. I have a function in Model:
public function getDatRev() {
if ($this->rev) {
return $this->rev;
} else {
return $this->datum;
}
}
in the View until now I have used it like this:
$model->datRev;
and it would return the correct value. Now I don't know what has changed, maybe I was also updated the framework, but the old construct doesn't work anymore, and in order to make it work I have to change it to:
$model->getDatRev();
Can you please explain to me why that is?
When you try get property the Yii2 calls magic method __get (). Return value is depend from implementation of this method in parent class. Yii2 can check if this property exist in some container, or if exist getter of this property.
In your case seems like you don't call parent's method __get(). This may have happened because you override __get() method or initialized this property.
Your class needs to extend yii\base\Object (directly or not) in order to use short property syntax ($model->abc instead of $model->getAbc()). Magic method __get() #Timur mentioned is defined there and further extended in yii\base\Component class.
I would like two different methods to be called depending on whether the request is GET /things/123 or GET /things/123?preview
Obviously, this would be a workaround:
[RoputePrefix("api/things")]
...
[HttpGet, Route("{id}")]
public object GetThing(int id)
{
if (Request.RequestUri.Query == "?preview")
return GetPreview(id);
else
return GetFull(id);
}
...at which point it's almost like using bool preview = false as a parameter and adding ?preview=true to the request. But I want this syntax instead and would prefer to handle it with routing if possible.
For reasons not shown here, I can't do the next easiest thing, which is to use /preview as a suffix.
I have been digging in the core of Laravel because I would like to understand how it works. But I come up with a method that I just cannot wrap my head around even after 3 days.
In start.php the app is binded to itself. So far so good. But when I check the $app->share method I am lost.
public function share(Closure $closure)
{
return function($container) use ($closure)
{
// We'll simply declare a static variable within the Closures and if
// it has not been set we'll execute the given Closure to resolve
// the value and return it back to the consumers of the method.
static $object;
if (is_null($object))
{
$object = $closure($container);
}
return $object;
};
}
This method returns an anonymous function which when executed returns an instance of the app. Do I see that right? Why is this? Why do you want to return a closure and not just the instance. This seems like a strange way, but I am quite sure that there is a reason ;) ??
UPDATE
The line in start.php:
$app['app'] = $app->share(function($app) { return $app; });
So I would think that $app['app'] is a closure object. However if I do get_class the class is Illuminate\Foundation\Application .
Furthermore there is also no way to execute it as $app'app' will not work obviously.
$app is no normal array, it is actually an instance of Illuminate\Foundation\Application1, an extension of Illuminate\Container\Container2, which implements ArrayAccess. But you know this already, as that's where the share() method lives.
The container binds keys to closures, when the keys are accessed the value is fetched from memory or, on first access, the bound closure is called and the resulting value is returned. When a key is set on the container it is wrapped in a closure unless it is already a closure.
This provides a consistent internal interface for the container, so that the code is not constantly type checking its contents. It will also only load the references you actually use are into memory - it is thought that the footprint of a closure is lighter than that of a fully loaded class instance. But once loaded, you get the benefit of working with the same instance for the rest of the request.
Why the app is not registered on the container using instance() I don't know though - perhaps it produces recursive references in trace and dump output.
I have a wrapper class that is meant to get and set code from a property in one of my dbml's partial classes. The reason for the wrapper is for a specialized get, which pre-formats the value. Here's what the wrapper looks like (NOTE: this is not the actual code, but represents everything but the formatting accurately):
partial class Class1
{
public string PropertyFormatted
{
get
{
var ret = Property.Substring(1);
return ret;
}
set { Property = value; }
}
}
This wrapper is bound using Bind() in a formview for the edit page. For some reason, the wrapper's value is set twice on update and the second time through the value is re-assigned its original value (causing the property to remain, ultimately, unchanged). However, when the wrapper is replaced with the property itself, there is no problem with saving to the database.
Any ideas what may be the cause of this?
The dbContext should be automatically detecting changes via this method:
http://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbchangetracker.detectchanges(v=vs.103).aspx
You may have inadvertently disable auto detect changes or something of the like. Try manually calling the method and see if that makes a difference.
Good luck!
I have a situation where I'm editing a snippet of data within a larger context. The user submits this data to a specialized action for handling and redirects back to the parent page. Because it's a redirection, validation errors aren't getting automagically set, so I'm trying to work around that.
In the event of an error, I'm writing a validation_errors key to the session with a value of $model->validationErrors. In the form, though, I'd like to tell Cake to set each error so I can leverage my existing styles and not have to make a lot of changes to my $this->Form->input() methods.
Is something like this possible? Essentially, I'm looking to manually achieve the same result you'd get if a regular form was submitted and allowed to drop through with validation errors. I was hoping I could loop over each validation error and set the field error, but that's not making any change at all.
Thanks.
This can be achieved in the controller by
$this->Model->invalidate('fieldName', __('ErrorMessage', true));
If the values are available, you can also call
$this->Model->validates();
to validate all values with the validators defined in the model.
Save the data to the session and revalidate it.
function childAction() {
if(isset($this->data)) {
$this->Session->delete('invalid_data');
if($this->Test->save($this->data)) {
// ...
} else {
$this->Session->write('invalid_data', $this->data);
}
$this->redirect(array('action'=>'parentAction'));
}
}
function parentAction() {
if($this->Session->check('invalid_data')) {
// This will cause $this->Test->validationErrors to be populated
// Assuming your parent page has the form set up properly, the
// errors will be automagically filled. ie: $form->input('Test.field1')
$this->Test->set($this->Session->read('invalid_data'));
$this->Test->validates();
}
}
If you want to do the same with CakePHP 3, use the method "errors".