Errors.add with object instance as message - ruby

I have a form with a custom calendar validation routine. I want to be able to display a lot of dynamic information about the this error to the user.
In this sense errors.add(:base, "this is wrong because ...") would not cut it. So I got the idea to pass in an instance of the object that performs the actual validation to the errors array. I would leave it to the view to cherrypick the bits of information it wanted by calling methods on the instance.
In my model validation routine I have:
errors.add(:date_range, [calendar] )
In the view, I do this:
<p><%= #event.errors[:date_range].first.first.parse_events.to_sentence %></p>
I had to add the array literal, otherwise the empty? method that rails calls would fail.
Even though this works, it smells bad! I thought about using render_to_string instead, but obviously that cannot be called (or should not be called) from a model.
Any suggestions on how to improve this?

Related

Yii2: Why do validation errors not throw exceptions?

I'm not sure if this is limited to Yii2 or if it could be also discussed with other frameworks or even in general.
In Yii2 I can call validate() on a model object. This will return true or false. If it is false I can call getErrors() to see which validation problems currently exist within this object.
Why is this behavior implemented this way? Why does validate() not throw some ValidationExceptions? I find it also somehow strange that errors are part of the model object. Why are they not part of such an exception?
What are the advantages of this implementation? Why is it done this way? I would prefer exceptions. With this, I could better distinguish between desired and exceptional processing. All that is not desired is handled in catch blocks. The desired happens in try blocks. Isn't this a good idea?
Because in general the errors are used in combination with a form.
Let's say you have a form with some input fields (linked to the model attributes/properties) and you want to do something with these fields, maybe save them or something.
Before saving the fields you would like to verify that they are all valid. When the validate() method is called all attributes are validated one by one and each one will generate an error if needed. If the validation is false and you have an error collection you can again show the form, but this time attach the errors to the fields.
If you throw an exception each time an error occurs your application would stop running and only display the one error. Or you would have to write try-catch blocks for all attributes, which is just unnecessary. When your validation returns true you can run the next step which does the processing and you can be sure all values are valid.
If you really want exceptions you can, of course, write your own Validators (http://www.yiiframework.com/doc-2.0/yii-validators-validator.html)

Is there a way to combine page object gem and javascript calls

Im using the page object gem and selenium,
when filling in a sign up form, the form fills in correctly, but when clicking apply it errors saying the fields are required even though they are filled in.
this seems to be caused because the page object/selenium method isn't firing the javascript change method which is needed for the application to know the field has been filled in
this can be fixed by using code such as
on(SettingsPage).payment_method_account_number = number
#browser.execute_script("$('input[name=account_number]').change()")
but this is obviously not ideal and breaks the whole point of using page object in the first place by having to declare the fields name attribute again
is there a way better way to solve this problem than what i have shown?
To avoid duplicating an element definition within the page object as well as the execute_script script, you can pass the page object element to the script.
The underlying Selenium-WebDriver (and therefore the Page-Object gem) supports an arguments array within the script being executed. This arguments array basically takes a Selenium-WebDriver elements and converts them to something usable by the script. The Page-Object execute_script method handles the conversion of elements to the right type, so you simply need to:
Declare a script that uses the arguments array
Pass in a PageObject::Element
For example, let us assume your page object has used the accessor:
text_field(:payment_method_account_number, :name => 'account_number')
Therefore, the page object will have a payment_method_account_number_element method that returns the PageObject::Element for this text field.
Within the script you want to execute, you can replace how you locate the element with the arguments array and pass in the PageObject::Element to the execute_script method:
execute_script("$(arguments[0]).change();", payment_method_account_number_element)
Then you can re-write the call to on as:
on(SettingsPage) do |page|
page.payment_method_account_number = number
page.execute_script("$(arguments[0]).change();", page.payment_method_account_number_element)
end
(Or, as Dane pointed out, put this into a method in the page object.)
I have had a similar problem but the event was "onblur" instead of "onchange". I would imagine the on change would fire, but if it doesn't you could use an approach similar to mine. I ended up creating a widget that redefined the "#{name}=" method to also call the event on the spot. It's a little bit more complicated, but it centralizes all the magic to one class and keeps the code brief.

Unhappy with the rail way of rendering partials

my question considers the partial handling in Rails. I just can't get the reason for some design decisions.
If I render a partial like this:
<%= render partial: 'foo/bar', object: #herbie %>
Where #herbie is an object of class Car. Why is the local variable called bar by default instead of car which - at least for me - would be more reasonable in most cases.
If various partials share a common layout I have to add the layout: ... each time I use render partial:. This seems odd to me! Isn't it more likely to have various partials wich share the same layout then the other way around? Wouldn't it be more reasonable to define the layout within the partial, or to add a to_layout_path method to the ActiveRecord Model?
Update:
I get the point that it might be better to use the partial name, as this is well known in the partial context. However the use of the tags :locals and :as screws up this argumentation.
In an actual case I want to use different partials depending on the state of an object (questions that could be open or closed). I moved the decision which partial to render to the Question.to_partial_path method which seems to be quite elegant. However I named the partials open_question and closed_question and this makes the partial code unreadable.
It gets even worse if I consider different types of questions.
I expect that within a partial we always make some presumptions about the model that is passed in. Thus in closed_question I am quit sure that I get a question - thus I would expect the variable to be called question. On the other hand I can imagine situations where we pass in something different that just behaves appropriated (Duck-typing).
My temporal meaning about partials is that within the partial it should be possible to define the name of the given parameter as well as a layout file that is used.
The parameter indeed can be realized by introducing a new variable ( question = open_question) which feels a little bit unclean to me.
When you pass in an argument to a method there's no way of knowing what the "name" of that variable is. The only thing the partial rendering method here has at its disposal is the foo/bar name, the object attribute, and some model.
That your model originated in a variable called #car is completely lost in the process of making the call.
It's convention in Rails that the variable used within the partial is the same as the name of the partial itself. You can override this if you want to have non-standard behaviour:
render(partial: 'foo/bar', locals: { car: #car })
As a note, though, going down the non-standard path is usually a bad idea. Whenever possible, just rename your partial to better match your expectations.
This is related: render partial :object vs :locals
The documentation is pretty good: http://api.rubyonrails.org/classes/ActionView/PartialRenderer.html
The default is to name the object after the partial. If you want to be explicit, you can use :as or locals.
render partial: 'foo/bar', locals: {car: #car}
render partial: 'foo/bar', object: #car, as: 'car'

RESTful design pattern in MVC?

I'm designing an application trying to follow the REST spec. I'm trying to figure out the best way to design it.
So let's say I'm doing a POST call that so I have a "post" method in my controller and model
// in controller
function post()
{
//call post model here
}
In my post request I need to make the following checks:
-validate fields
-make sure item name is unique for that user
-make sure there are less than 10 items
-etc (there could be more cases)
Now in controller post function I will return a REST message and status code based on whatever happens, which is fine, but I'm curious to know where it's better to keep all those checks.
I can put all the checks in the model and then return some kind of array like:
array('text' => 'return response text/array or whatever here', 'code' => '200/400/etc')
Then just return this in the controller, or is it better to break up those checks into individual functions within the model and then do all the checks in the controller?
// in controller
function post()
{
//if validation fails -> send response
//if name is not unique -> send response
//etc...
}
From a design point of view, if I ever wanted to potentially call the "post" method in the project model from other methods, it would not have an all encompassing function to handle it, however if I do keep it all in one model function it doesn't give me a lot of reusability. If I had to pick sides, chances are I probably wouldn't need to reuse those "check functions" too much anyway, however it also seems weird to have all that response info in the model rather than the controller.
Can anyone please give me some input on this.
I would not create post method inside the model (although having it in the controller is perfectly fine) simply because you just put code/model in such a frame that is not re-usable plus less readable. For instance, instead of post method in the model I would create create method.
There is no one-fits-all way for data validation. I like creating validation classes which have only one method validate for various data types (e.g. username validation class checks if it matches regex and is unique). It's better than copy pasting the validation code to every action (DRY). Where to call this class method? It depends. You can simply call that it in the action. Since the validation code is inside the validation class, it will look alright. You can also create a mapper which takes the request, determines what validations have to be performed and etc. but it might be overkill and is hard to do properly (maintainability wise).
For output again - DRY. It depends on what MVC framework are you using and there might be a good solution for this already. If not, you can create a class for that (yup, I am DRY maniac). You pass response code, array (or string) with response and class nicely wraps everything into JSON, XML format. Advantages: if you change then output format then you need to change only in one place.
Also consider using Remote Facade pattern.
Hopefully, you found something useful in this post.
I would separate the API from the MVC application and use Apify

Help me better understand Struts2, validation, and stateful actions

As I understand it, Struts2 action class instances can (unlike Struts1) be stateful, because each GET or POST to an action creates a new instance of the backing action class.
I also see that there's a standard(?) idiom (Pattern?) to provide input forms: the same .jsp is used as the View component of two different actions, like this:
<action name="showForm" class="defaultActionThatDoesNothingExceptReturnSuccess">
<result name="success">inputForm.jsp</result>
</action>
<action name="validateAndProcessForm" class="realAction">
<result name="input">inputForm.jsp</result>
<result name="success">formProcessed.jsp</result>
</action>
The first action just displays the form, without validating the input or processing it. The form in the .jsp posts to the second action:
<s:form action="validateAndProcessForm" method="post">
and that second action validates the posted fields/parameters, returning "input" if the form's inputs are incomplete or invalid, or actually calling the action class's execute if the inputs are complete and valid, thus processing the form and returning the (e.g.) formProcessed.jsp that displays something like "thanks for your input!".
So we have this sort of "picket fence" idiom:
defaultAction- -> realAction-
| | | |
-> input.jsp- <--- -> success.jsp
This is done so that the first time input.jsp is displayed, validations aren't called (and so validation errors are not shown), but that after the submit button on that jsp is clicked, the "real" action will validate the input, possibly passing back errors calling out invalid input which the input.jsp will display.
Which brings us back to stateful, non-singleton actions; because the action is stateful and thus not shared across GETs or POSTs, and each instance is instantiated just for that GET or POST, the action has no way to know if a particular session has "GETted" the same page multiple times. So GETting showForm.action will never validate, and GETing validateAndProcessForm will always validate (and show errors if the parameters are invalid), even if that GET is the first time a particular session has "GETted" that URL.
Which is why we need the "fence post": the first action just to display the form, the second to capture the input.
Is my understanding correct? Is there a less verbose way to do this, to not validate input on the initial GET, but to validate on the POST, without having to have two actions for every form?
There is another way to perform what you want without the picket fence. The validation interceptor, by default, does not fire for the input method. You can therefore update your struts.xml to the following:
<action name="*MyForm" method="{1}" class="realAction">
<result name="input">inputForm.jsp</result>
<result name="success">formProcessed.jsp</result>
</action>
With this setup, you do not need the empty action at all. When you first go to the form, you would go to the url "inputMyForm", and have your form action just point to "MyForm". The {1} in the method block just means that the framework will call whatever method matches the * from the action name. If the * match is empty, it defaults to the execute method. So you get the following kinds of actions:
inputMyForm would go to the input() method of your action class
MyForm would go to the execute() method of your action class
executeMyForm would go to the execute() method of your action class
customMethodNameMyForm would go to the customMethodName() method of your action class
Since the validator interceptor excludes any actions going to the input method, you can set up whatever validation you want for this action, and it will only look for it when you submit the form. Since every time you submit the form, it is going to the execute method, the validation will occur every time you submit the form.
Also, if you are extending the ActionSupport class, that class already defines the input() method, so you would not even need to change your action class to accomplish this.
It's possible to do things differently but lets say you let struts2 handle all the requests. Everything that struts2 handles is an "action".
Don't worry about GET or POST they are just two different methods of sending data to an action, if there are parameters (regardless if they are get or set) then struts2 will try to place that data onto the actions class (assuming there is one). If there is a validation method (or a properly named validation xml file) then validation will be run after the class properties are set. Then the execute() method for the class is called (assuming there is a class). After this a jsp is typically rendered which has at its disposal all the public data in the action's method.
Take your "showForm" action... you can reduce the xml to:
<action name="showForm">
<result>inputForm.jsp</result>
</action>
You can see you don't need to define a class. Further the default result is success so we don't need to mention that either.
So when thinking of hmtl we would think in terms of pages. When thinking in struts we think in terms of actions, they only need to be as complicated as necessary. That is if you need to show a form then you need a show form action, if you want a display page that uses the form data then you need a "displayPage" action which does something with the form data.
So think of each action as starting with a url > ----------- > ending with returning date (generally rendering a jsp). The dashes are the optional parts that you may define, but if you don't they will sensibly default for you. To see what features are provided to you you'll need to look in struts2-core-x.x.x.x.jar and view the contents of the struts-default.xml that is where "defaultStack" is defined. Each interceptor in turn is called, knowing what they offer (and the other interceptors offer) let you know what you get out of the box (I wouldn't look into them too deeply just know they are there so you'll know for instance that if you need to upload a file the simple fact that the "fileUpload" intercepter is in the default stack should be indication enough that there must be built in file uploading capabilities.
So no there is not a "false action" to the input form. It is a real action abet a simple one. After you learn how to define packages, actions, default actions for a package and perhaps globally and learn how to define an interceptor then you should look at the conventions plug in. It makes life a lot easier!
Your question makes sense. Your pattern is correct, though:
as Quaternion pointed out, there is little or no "verbosity". Your first "showForm" is a dummy "action mapping", its "do nothing" class does not need a particular class definition (the default ActionSupport is enough).
there are other possible patterns; some people might prefer the idiom you are pointing out (and it has a long history - I remember doing some pelr CGI pages in that way, centuries ago) : use a single url (and hence a single action mapping) for the two "steps" (show the initial form and process the form), by guessing inside the action method (or in the validator) the current step, perhaps by checking that some parameter is present (perhaps a hidden field) or perhaps by discriminating POST/GET. In Struts2, I prefer the other way, in general.
BTW, calling the Struts2 actions "stateful" is correct only if you undestand (you do, apparently) that that 'state' does not survive among requests.

Resources