Best approach - Conditions in the view - ruby-on-rails

I have a model with attibutes name, title, description ect. If the name is by example weather-foracast I want to show an extra html element
= high_chart("my_id", #chart)
in the show template, wich generates a nice chart. When the page is not weather-foracast i don't want to show the chart.
What is the best approach? Conditions in the view?

Your problem looks really close to the Exhibit Pattern presented in Object on Rails.
Simply explained, the solution proposed is to wrap your model in a decorator (or multiple decorators) chosen using the state of your model (in your case the name of the record).
I cannot explain it as well as it is explained in the book but that Pattern is so useful that Avdi Grimm made a gem out of it : https://github.com/objects-on-rails/display-case

I know this answer is totally over the top, but something to consider is moving your conditional logic outside of your views.
Maybe going with the View Presenter pattern, see this:
About presenter pattern in rails. is a better way to do it?
Presenters are ruby objects and can be tested really easily.
Whereas having tons of logic inside the view is really hard to test.
Furthermore, you want isolation of logic, checking for model.name inside your view page is not the best way of MVC.

Since it looks like you're HAML, you can just use an if modifier like so:
= high_chart("my_id", #chart) if [model.name] == "weather-forecast"
where [model.name] is replaced with the appropriate code.

Related

MVC - how to define reusable paragraph I could use on any page?

I am beginning with MVC ASP.NET and stumbled upon a problem. There is a paragraph (some 5 sentences) I would like to use on several of my child pages. This text changes quite often so I would like to have it defined on 1 place so I dont have to update like 10 pages when it changes again.
Problem is, that I dont know how to do it. I was thinking about using CSS (which should be used for styling, not text) or sections (doesnt work, as each child page needs its own sections defined).
Could someone advise me the most optimal and "correct" way to achieve this? I would like to define this paragraph at one place and then "call it" from the child page without need to use the database. Which approach should I choose?
Thank you
Create one partial view and call in your main view:
#Html.Partial("YourPartialViewName", Model) //if you have some dynamic data pass in model

How split one big View into small Views in MVC

Consider u have a big front page include ton of data from database (like new products,best products, latest posts, banners,sliders,etc) not only static views like header or something like that. related to this post
it seems this is better to build a complex model and split page to small partial views. but what is wrong with this way that USE ACTIONS and split page like this:
#{
ViewBag.Title = "Home";
}
#{Html.RenderAction("Header", "Home");}
#{Html.RenderAction("Sliders", "Home");}
#{Html.RenderAction("Specials", "Home");}
#{Html.RenderAction("Services", "Home");}
...
#{Html.RenderAction("Footer", "Home");}
so you no need to use a complex model.
EDIT: my main question is what is wrong with using actions in view instead partial views. in this way you no need to send a complex model to view and use its parts for partial views
Using partial views makes the code easier to maintain, since partial views are by convention named with an underscore like "_PartialView"
this way you can easily see in your solution which views are partial and which are not.
How you want to implement them is a question of heart and experience most often, but always strive for best practice.
That is, try to code the way you think you want to read code when coming back after a long break from it, or how you want to find code written by others that you think is easy to understand fast.
The less cognitive strain, the better, whether the code is for you or someone else.

ASP.NET MVC View Model Naming Conventions

I know I will probably get a mixed opinion on this, but I was wondering if there were and "Best Practices" for model naming conventions.
I have a rather large application and I have adopted the following model naming convention:
Models
Add
CategoryAddModel
ProductAddModel
Edit
CategoryEditModel
ProductEditModel
View
CategoryViewModel
ProductViewModel
I was thinking of the following as well:
Models
Add
AddCategoryModel
AddProductModel
Edit
EditCategoryModel
EditProductModel
View
ViewCategoryModel
ViewProductModel
Which do you prefer, and why?
Do you think it really matters?
I prefer like {ViewName}{Controller}ViewModel. I also remove Models folder, instead I put view models in ViewModels folder. That makes more sense to me.
eg. AddCategoryViewModel
It doesn't matter. You should name things in a consistent, logical, and straightforward way. Basically, just pick something that makes sense and makes you most productive. Consider how your naming convention would work with IntelliSense.
You might also want to consider how easy your code will be to maintain a year from now.
To pull out Hightmaston's comment into a formal answer for clarity.
A logical template to follow would be:
{Controller}{ViewName}ViewModel
This encourages better file organization at scale, and reduces the number of Intellisense "hits".
A simple example might be as follows:
CategoryIndexViewModel
For brevity you may also consider:
CategoryIndexModel
In theory CategoryViewModel, CategoryAddModel and CategoryEditModel will contain the same properties, so there is little point tripling the number of view models you have in your UI. Just CategoryModel should suffice. It's the type of HTTP requests being received by your controller which defines whether it's a GET or POST operation. The model used to populate a view for a GET, or capture form data for a POST will be the same type either way.

Should the model be responsible for holding lists that will ultimately populate dropdownlists in the view?

This might be similar to ASP.NET MVC - Populate Commonly Used Dropdownlists.
I want to populate DropDownLists. Some of it is static data. Some of it comes from the Database. A couple of times I found myself forgetting to call the code that populates my lists and sets the ViewBag accordingly. It is almost worth adding a unit test for this. The only way I think that this suits a unit test is if you place it in model/service. Is there a best practice for this kind of thing?
I'd suggest that the data is contained within the model but is perhaps constructed by a html.helper method. this way, you keep the plumbing markup out of the view and leave the controller free to invoke the neccesary view and model.
You could also of course hand it off to a partialview with an <IList<SelectList>> model.
cats and their skin :)
If you follow the spirit of the pattern then the Model should supply the View with everything it needs to present to the user that's not static. If you have static dropdown lists then you could say that these could be constructed within the mark-up. If you are passing a SelectList to the View from your Action then I'd stick it in the Model to make things simpler and more coherent.
My rule of thumb is that the data must somehow be in the model, either as a ready to use SelectList or at worst in some container that can easily be turned into a SelectList using a LINQ-to-object call.
The bottom line is that the view should never contain any non trivial code.
EDIT (answer to your comment):
I try not to put too much code in models. Models are more like a simple bunch of data gathered by the controller and used by the view.
Regarding simple and/or common things such as the days of week, I believe an HTML helper is the most elegant solution. See WayneC's answer in this question.

How do I sort the rows in a nested object form in rails for just one view?

When working with a nested model in a form, is there a way to sort the nested models in the view or in the controller? The closest answer I could find was here, but both of those solutions involve putting sort orders in the model. I'd rather avoid changing things fundamentally like that and keep this particular sort order to just one page.
You can always sort with ruby: parent.children.sort{|a,b| a.field <=> b.field} or something like that
Or you can add a find method to parent model, like def self.find_ordered_by_field
Can't think of another options...
Putting the sort in the models is absolutely the way to go. You shouldn't have any more ruby code than necessary in your views themselves, because it's much harder to test that your sorting is working the way you think it should.
When you add the sort at the model level (and either answer in the link you posted works well) you can add an automated test to verify that it is, in fact, sorting the way you'd like. This is business logic, and it belongs in the model.
Sometimes, however, you're looking to sort in a way that is NOT what you would normally want for this model. Maybe you normally want them sorted by name, but in this one view you want them sorted newest to oldest. At the very least, do the sort in the controller so once again it can be fully tested. But I would still put it in the model, personally.

Resources