- Read Tutorial
- Watch Guide Video
Continuing down our list of tasks you can see that our next item is walking through how to integrate view helpers. Before we do that let's talk about what a view helper is. Now helpers are kind of similar to partials and I'm going walk through how they're similar in a basic demo here first.
In the views/shared we have our nav partial. A partial is an HTML file that you can call and can be shared across a number of views and that is what a partial is. Now a view helper method in Rails has some similarities in the sense that you can call it from anywhere in your view files and you can slide in HTML. But the difference is that a helper is going to be written in Ruby. Where our partials are written in each HTML, now there is crossover. I'm going to come into helper's which is in app/helpers, if I click on application helper right here you can see that we have a module called application helper.
I'm going to create a very basic helper here, first I'm going to say def sample_helper. Our helper methods are just regular Ruby methods now inside of this, I can put a tag "My helper" and close up the tag. One thing you have to do because this is a Ruby method, this will not work just like this, I have to add HTML_safe.
module ApplicationHelper def sample_helper "<p>My helper</p>".html_safe end end
This will get processed and then click on simple helper and let's open up the home page view.
Coming down or get all horizontal rule tag for some separation and then use embedded Ruby and then call sample helper.
<%= sample_helper %>
This is going to be routed to the application helper and it's going to say Okay is there any method called sample helper? If there is I want you to show this code anything that's inside of it right here.
I'm going to start up the
rails s and let's open up our portfolio and click on home.
You can see that on the bottom where it says, my helper. This is working perfectly. Let's take a look at what happened if I pulled off the html_safe and hit refresh.
That is exactly what should happen right here. The reason for this is because all this is at the end of the day is a string. In this case it's getting treated like a regular string. What Rails does is it sanitizes the string, so it doesn't get automatically rendered as HTML. Instead, it gets cleaned out and this is for your protection and for the protection of your users because imagine that inside of one of these methods you took user input. You wired this up to your comment section and this filtered some of the comment content. If a user put HTML code and put some malicious script in there, it might be able to make it into your database might be able to perform some type of malicious kind of corruption something like that. Being able to have this cleaned up and not automatically render the HTML code is actually a good thing.
In our case, it's fine to say html_safe and the kind of a good rule of thumb for knowing when it's okay to do it versus when not, is if you have to deal with user input then you're probably not going to use html_safe. If you're dealing only with content that you've written or that you own then it should be fine to put html_safe.
If I come back and refresh that is now working, That is a really basic example, Why would I want to call this simple helper and call that right here? Wouldn't it just be easier for me to copy this and put it right here? Yes, it would. The point of an application helper or any view helper method is not just purely to render HTML. That would kind of be pointless. I wanted to illustrate that so you could see one of the key differences between partials and view helpers. The purpose of the view helpers is whenever you need to have some conditional logic. A great example and it's actually the one we're going to implement next is let's say that we for the sake of argument and because it's accurate, say that we don't like our HTML file having all of this conditional logic right here or we says if the current user is a user then show logout. Other than that show register a login. I would hate to have this inside of my master layout file. Also, we have a few other issues because if we open up the blog.html.rb, we have identical code. If we open up the portfolio.html.rb, we have identical code there as well.
We have three layouts that all have identical code.
If I wanted to change this and say Sign up now we're going to have to make the change in three spots just like we talked about with the purpose for having this nav partial. There are some similar reasons why it is important and why we want to have a helper method. The reason why I don't believe in just putting this inside of a partial is because of some best practice reasons.
Typically you want to leave your conditional logic outside of your views directly. By having this here even if we move this in a partial It really isn't a good clean coding practice. The reason for that is look at this code, do you see any HTML in here whatsoever? No, there is none. All it's doing is having a bunch of these little embedded Ruby statements. We can pull all of that out, go into our application helper and we'll call this login Helper. Paste this in.
module ApplicationHelper def login_helper if current_user.is_a?(user) link_to "Logout", destroy_user_session_path, method: :delete else link_to "Sign", new_user_registration_path link_to "Login", new_user_session_path end end end
Hit save. With login_helper we can come back to this file (application.html.erb) and paste in
<%= login_helper %> the same way we did that little sample helper test. Now if I come back to the site and hit refresh, we have a little error because I deleted sample_helper. Come back to home.html.erb and delete all that.
Now refresh and there you go. Notice how our login helper is still working. Everything here is still working perfectly if I login it gives me all my nice conditional logic. But we've removed it from the view and instead, we now have just a very nice clean call to the login helper. Another thing I like about this is it's very explicit. This tells me right away that this has to deal with logins.
If I come to the blog, I can now remove all of that code (lines 17-22) and come to the portfolio, delete all of that (lines 19-24) and hit save. Come back hit refresh. Now we can go and click on each one of these other items like blog and portfolio and everything is still working perfectly. This is really cool. I love implementing these kinds of coding practices because this has so many benefits. One it's much easier to read, this code right away tells you this is where my login logic is going. Any time I need to make a change such as saying sign up I could sign up just like that. Come back, refresh, click logout, now it's going to say sign up.
Right here this is Ruby code so we can treat these items like normal HTML so when I copied and pasted this, it worked perfectly fine in regards to how you would process HTML but this is a Ruby method. If you remember how Ruby methods work whatever the last item is that gets returned as true is what is going to be returned by the method. Understanding the data flow,
open pry in terminal
I think this is worth the time of taking and seeing exactly what's happening here and why. What I first implemented didn't work.
If I hit return and call sample_method it's going to return "Yea" that makes sense. But now what happens if I come back here and I change the value of x to 2 and come back. Run all of this again and now run sample_method again, it returns "something." Do you notice what it did? It skipped over "No." Now notice how this looks kind of similar to what we have going on right here. What happens in Ruby is we have these two link_to statements. But these are just method calls so you can think of these as being completely separate entities. Ruby doesn't wrap all of this up, just like it did here, it doesn't wrap the entire item up. Instead, it says okay the last object that gets returned, that is what comes back. That's why something got printed out. If you delete this if you come back to the application that's why only login is showing. Look this is the last thing that got returned. How do we fix this? Is this possible? Absolutely. Thankfully the fix for this is actually quite simple.
You just and I've done this one before. You simply have to wrap these items into their parentheses. We're going to connect these and then we can just concatenate them so we can just hit + and then what Ruby's going to do this is exactly the same as if I put all of this on one line. and so it's going to return this entire item. I'm going to do a plus here and put them on two lines just for making it easier to read.
If I come hit refresh Now you can see it says sign up login. It's both on one line which we don't want but we can fix that as well because we can just add another plus. Here we can put this is not going to be our final implementation but we can put a brake tag with html_safe and then we can add that. This is going to say give me the sign-up link then give me a break which means put this on a new line in HTML and then connect that with login. Since we use the plus operator it's the same as putting them all on one line. Now this entire item will get returned
Hit save come back and there you go. Now we have the behavior we're looking for. now it shows us our logout click that and now we have sign up and login. Notice how easy that was in regards to making a single change. I know I made that little blunder that only returned one. But in terms of making a change if I now change this back to register I only have to make the change in one spot and if I go to portfolio it says register I go to a blog it says register and all of that's possible because we're using a view helper instead of having this identical code in three different layout files.
The last thing that I want to leave you with on this guide is talking about the difference. When do you know when to use a view helper compared with when to use a partial. I have a rule of thumb that I personally follow which is that these type of helper methods if the logic that I'm trying to implement in the view has things such as conditionals. if it has the majority of the logic is based on Ruby code where you need to do things like if/else statements or case statements or anything like that. Exactly like what we have right here. Then I will use a view helper.
If I have something like the nav where the majority of it is HTML code, then I will use a partial. That's usually how I do it. There is not truly a right or wrong way of doing. I've seen some developers that tend to use view helpers all over the place and I've seen others that put the majority of their code in partials. A lot of it comes down to what your application requires. I would definitely keep your eyes open play with all the implementations and get a feel for it. The more you do it and more practice you'll get at it and you'll start to know what implementation works for your specific app.
- git status
- git add .
- git commit -m "Implemented view helper for auth links"
- git push origin view
If I come back into our pivotal tracker we can come here and we have now finished integrating view helpers.
Now in the next guide, we're going to continue working with new helpers but we're going to see how we can use some very cool HTML generating methods inside of them.