I find myself writing a lot of code in my views that looks like the code below. In this case, I want to add some explanatory HTML for a novice, and different HTML for an expert user.
<% if (ViewData["novice"] != null ) { %>
some extra HTML for a novice
<% } else { %>
some HTML for an expert
<% } %>
This is presentation logic, so it makes sense that it is in a view vs the controller. However, it gets ugly really fast, especially when ReSharper wants to move all the braces around to make it even uglier (is there a way to turn that off for views?).
My question is whether this is proper, or should I branch in the controller to two separate views? If I do two views, I will have a lot of duplicated HTML to maintain.
Or should I do two separate views with a shared partial view of the stuff that is in common?
Ideally, this kind of logic would be handled in the view model and the view should just be rendering the model.
So you might have something like in your view:
<%= ViewData["helptext"] %>
and your logic in the controller would be something like:
ViewData["helpText"] = isNovice ? noviceText : expertText;
that way you can push that logic back to the controller and keep your views nice and clean
You're trying to create 2 completely separate html pages with identical models. You want a separate view. Don't try to out clever the design pattern with conditional-branching logic.
HTML helpers aren't going to help you much here, since it appears you will not be repeating much logic other than if else.
Related
In a fairly large rails application we are running into the issue of overly complex views. Most of the views have too much logic.
Views have between 2 and 4 related instance variables, and make use of various logic checks and helper methods to render the view.
Here is a fake example:
<% if authorized?(#user) %>
<!--some html-->
<% recent_projects(#projects).each do |project| %>
<!-- html & helper methods -->
<% end %>
<!--some more html-->
<% else %>
<!--some html & helper methods-->
<% end %>
Presenters, Facades, and helpers:
I've been researching using the facade and/or presenter pattern to help expose the functionality we need in the view while extracting and isolating the complexity.
My Question is:
Where does the html live? Do I make several small view partials and render them conditionally from helper methods? Do I create a presenter which has methods that handle the logic and output of the html (using content_tag, etc)?
Any general "best practices" or guidance would be appreciated. If I haven't been clear ask questions and I will respond quickly.
I'm unsure what the best practice is specifically but what I think is that making smaller view partials is the way to go so that the view code is separated and can be separately maintained. Your presentation logic resides inside a Presenter class and renders appropriate partials from app/views.
I think that using content_tag is going to make your UI designer think, say, how to add a css class to an element, ultimately leading to more maintenance time. content_tags are fine if they are smaller and are not frequently updated in terms of styling.
Another point to keep in mind is if you are a developer who is also after cleanliness of code then imagine writing a content_tag for multi-line block of <div /> with paragraph of text with multiple inner tags. You'd have to start manipulating strings to handle this and sometimes it become time consuming to yourself and other developers to follow the code.
I'm sure there are many more goodies of keeping the view template separate from Presenters but the point mentioned above is one that I learned from one of my recent projects.
Just learning rails and looking for best practices help. I have the same data table that is reused across several different views (index, search results) for my controller. In an attempt to keep it DRY I have the table code in a helper method using html<< for table HTML.
I realize that now I've pulled a chunk of my HTML into the controller which I'm not a big fan of. How is this situation of having a chunk of HTML you plan to reuse across several views handled best?
Thanks!
What you want are partials. You put the partials in the same folder as the views, but partials start with an underscore (e.g: app/views/user/_my_partial.html.erb). In this partial you can put the shared HTML code, and access it from the view with:
<%= render "my_partial" %>
Yes you skip the underscore when you access the partial.
See the rails guide for more information on partials.
I have this code in my html.erb at many places.
<div id="left-nav">
<%= render :partial => 'tests/tests_left_menu' %>
</div>
Is it a good idea to create helper method for this type of code ?
How to write this code in helper ?
I see a few good strategies to use in your situation. Pick and choose based on your project's specific requirements.
You can just put div#left-nav and its contents into yet another partial like tests/tests_left_menu_with_wrapper. This saves you a couple of lines.
If you can generalize the cases when the entire segment appears, you can move it into a layout. This way, once you declare the layout for a particular action using the ActionController::Base.layout method, you'll be able to skip writing the entire segment altogether.
You can write a helper, but it's not clear what advantage it confers over simply using content_tag. You're probably better off using partials or layouts.
Personally i don't think there's a need to, and i think it's more like because you are not using other tools like haml to help reduce the number of lines in an erb files
the same code can be achieved in haml in just 1 line:
#left-nav= render :partial => 'tests/tests_left_menu'
hope this helps =)
I suppose if you have that code in many places I'd move the the div into the partial. If you need the flexibility to have tests_left_menu outside of the div I'd still pick two partials over a helper in this scenario. Avoid writing html in Ruby when you can :)
I am used to using a Repeater control in conventional ASP.Net web projects. I see ASP.Net MVC doesn't have this sort of thing. What should I be using here?
EDIT:
In response to the question, what am I trying to do that I can't achieve in the foreach. I guess I am trying to get a alternating row style. Also, it just feels somewhat wrong to have stuff other than markup in the view. But maybe I will get over that as I work with it. Thanks for the answers.
The simplest thing to use is a foreach loop.
What are you trying to do?
EDIT:
<% bool odd = false;
foreach(var row in something) { %>
<tr class="<%= odd ? "OddRow" : "EvenRow" %>">
...
</tr>
<% odd = !odd; } %>
To add to SLaks response.
You could encapsulate your html into a Partial View.
Call <%= Html.Partial("ViewName", optional_ViewModel) %>.
This might feel closer to the repeater control. Where the PartialView would be sort of like your item template.
This approach also lends itself to code reuse very nicely.
If you miss a lot of the features of WebForms, maybe you just need a richer view engine? Might I suggest the Spark View Engine? Like WebForms, there's lots of functionality included so you don't have to keep rewriting the same stuff and/or write a bunch of your own helpers.
alternating row style can be achieved by css styles ... BTW - each one funcionality from web forms can be achieved in mvc ... in the end all is html, js and css
You could even create an HTML helper for this.
I have a 'template' system in my CMS rails app. Basically the whole HTML template is stored in a database column and it has key code in the string (like <!--THEME_Body-->) that gets replaced with content generated by the application.
I use an actual layout to render the template. All that is in the layout is:
<%= generate_theme.gsub!('<!--THEME_Body-->', yield) -%>
That helper takes the correct theme and further gsubs other area like Meta data and Breadcrumbs.
I'm just wondering if there's a better way to go about this? Perhaps using content_for or something like that?
That's a pretty good way of going about it, although I would make use of Ruby's sexy syntax to combine all the lines into something a little more syntactically correct - it speeds the script up and it looks a damn sight nicer too!
tags = {
'<!--THEME_Body-->' => yield,
'<!--THEME_Head-->' => yield(:head),
'<!--STYLESHEET-->' => stylesheet_link_tag('application')
}
tags.each { |str, rep| generate_theme.gsub!(str, rep) }
Bear in mind that this code should not go in a view - it should ideally be put in a model, as it's to do with the application's data, but it could also go in a helper somewhere. If it's an instance variable in a model, you could just call
generate_theme.parse
And that code could be executed - it looks a lot better and sticks to the standard MVC convention of cleaning up the view as much as possible.
Jamie