Skip to content

Instantly share code, notes, and snippets.

@waneka
Created October 7, 2013 21:55
Show Gist options
  • Save waneka/6875594 to your computer and use it in GitHub Desktop.
Save waneka/6875594 to your computer and use it in GitHub Desktop.
*Solution for Challenge: Research: View and Form Helpers. Started 2013-10-05T19:23:49+00:00*
# link_to
**link_to** is a rails helper that helps generate html link tags in views and controllers. ``link_to`` "relies on" (whatever that means) ``url_for`` - a similar (but different) helper that generates links in views and controllers. From the [ActionView docs] (http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to):
```ruby
link_to(name = nil, options = nil, html_options = nil, &block)
```
*Creates a link tag of the given name using a URL created by the set of options.*
Some examples:
1. **Helper**
```ruby
link_to "Profile", @profile
```
**Produces html**
```html
<a href="/profiles/1">Profile</a>
```
**Explanation:**
Here ``link_to`` produces an html link tag. In this example, the text of the link comes from the first argument ("Profile"), and the RESTful route is provided by the class and id of the second argument, in this case the instance variable `@profile`. From the docs for [url_for] (http://apidock.com/rails/ActionView/Helpers/UrlHelper/url_for): *Passing a record (like an Active Record or Active Resource) instead of a Hash as the options parameter will trigger the named route for that record. The lookup will happen on the name of the class. So passing a Workshop object will attempt to use the workshop_path route.*
2. **Helper**
```ruby
link_to "Profile", profiles_path
```
**Produces html:**
```html
<a href="/profiles">Profile</a>
```
**Explanation:**
As above, the text of the link comes from the first argument ("Profile"). In this case, the route ("/profiles") comes from `profiles_path` -- a "[resourceful route](http://guides.rubyonrails.org/routing.html#resource-routing-the-rails-default)" named in `config/routes.rb`
3. **Helper:**
```ruby
link_to "Articles", articles_path, id: "news", class: "article"
```
**Produces html:**
```html
<a href="/articles" class="article" id="news">articles</a>
```
**Explanation:**
Here, ``link_to`` produces classes and an id for CSS in addition to the html link tag. As before, this example assumes a route named "articles_path" has been specified in `config/routes.rb`
4. **Helper:**
```ruby
<%= link_to(@profile) do %>
<strong><%= @profile.name %></strong> -- <span>Check it out!</span>
<% end %>
```
**Produces html:**
```html
<a href="/profiles/1">
<strong>David</strong> -- <span>Check it out!</span>
</a>
```
**Explanation:**
In this example we pass a block to ``link_to``. The primary use of blocks with ``link_to`` seems to be when your link text itself is complex, has variables or includes other complicated styling, like ``<span>``
**See the [ActionView docs](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) for other examples and uses of link_to !!**
# image_tag
**image_tag** is an ActionView helper that writes an html image tag.
```ruby
image_tag(source, options={})
```
From the [ActionView AssetTag helper docs](http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-image_tag): *image_tag returns an HTML image tag for the source. The source can be a full path or a file.You can add HTML attributes using the options.*
Some examples:
1. **Helper**
```ruby
image_tag("icon")
```
**Produces html**
```html
<img alt="Icon" src="/assets/icon" />
```
**Explanation:**
Here ``image_tag`` generates the html img tag, including the default "alt text" with the same name as the source. As of Rails 3.1, the image source ("src"), if not otherwise specified, is assumed to be your assets folder: /app/assets/images (if you have not disabled the default asset pipeline). In production, assets will be compiled to public/. If this is confusing, you are not alone. More here on the [asset pipeline] (http://guides.rubyonrails.org/asset_pipeline.html).
2. **Helper**
```ruby
image_tag("/icons/icon.gif", size: "16", alt: "Edit Entry")
```
**Produces html**
```html
<img src="/icons/icon.gif" width="16" height="16" alt="Edit Entry" />
```
**Explanation:**
Here ``image_tag`` generates a link to an image in a non-standard path (though, here again, I assume that you need to physically put icon.gif in app/assets/icons/). This example also shows how you can set width and height with "size", as well as custom "alt text" with "alt".
3. **Helper**
```ruby
image_tag("/icons/icon.gif", class: "menu_icon")
```
**Produces html**
```html
<img alt="Icon" class="menu_icon" src="/icons/icon.gif" />
```
**Explanation:**
This final example shows how the ``image_tag`` helper can be used to add css classes to your image tags. The same holds true for id or other html attributes.
**See the [ActionView docs](http://api.rubyonrails.org/classes/ActionView/Helpers/AssetTagHelper.html#method-i-image_tag) for other examples and uses of image_tag !!**
# form_for
takes in an active record object and constructs a form using the object's attributes
takes a block with one variable
Assume we have a controller for dealing with articles app/controllers/articles_controller.rb:
```ruby
def new
@article = Article.new
end
```
The corresponding view app/views/articles/new.html.erb using form_for looks like this:
```html
<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, size: "60x12" %>
<%= f.submit "Create" %>
<% end %>
```
There are a few things to note here:
* @article is the actual object being edited.
* There is a single hash of options. Routing options are passed in the :url hash, HTML options are passed in the :html hash. Also you can provide a :namespace option for your form to ensure uniqueness of id attributes on form elements. The namespace attribute will be prefixed with underscore on the generated HTML id.
* The form_for method yields a form builder object (the f variable).
* Methods to create form controls are called on the form builder object f
The resulting html is:
```ruby
<form accept-charset="UTF-8" action="/articles/create" method="post" class="nifty_form">
<input id="article_title" name="article[title]" type="text" />
<textarea id="article_body" name="article[body]" cols="60" rows="12"></textarea>
<input name="commit" type="submit" value="Create" />
</form>
```
```html
<%= form_for @person do |f| %> <%= f.label :first_name %>: <%= f.text_field :first_name %><br /> <%= f.label :last_name %>: <%= f.text_field :last_name %><br /> <%= f.submit %>
```
produces the following html:
```ruby
<formaction="/people"class="new_person"id="new_person"method="post"]]> <divstyle="margin:0;padding:0;display:inline"]]> <inputname="authenticity_token"type="hidden"value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg="/]]> </div> <label for="person_first_name">First name</label]]>: <inputid="person_first_name"name="person[first_name]"type="text"/]]><br/> <label for="person_last_name">Last name</label]]>: <inputid="person_last_name"name="person[last_name]"type="text"/]]><br/> <input name="commit" type="submit" value="Create Person" /]]>
```
and the following form_for call...
```ruby
<%=form_for(@user)do|f|%> <%=f.label:name%> <%=f.text_field:name%> <%=f.label:email%> <%=f.text_field:email%> <%=f.label:password%> <%=f.password_field:password%> <%=f.label:password_confirmation,"Confirmation"%> <%=f.password_field:password_confirmation%> <%=f.submit"Create my account",class:"btn btn-large btn-primary"%> <%end%>
```
produces the resulting html:
```
<formaccept-charset="UTF-8"action="/users"class="new_user" id="new_user"method="post"]]> <labelfor="user_name"]]>Name</label> <inputid="user_name"name="user[name]"type="text"/> <labelfor="user_email"]]>Email</label> <inputid="user_email"name="user[email]"type="text"/> <labelfor="user_password"]]>Password</label> <inputid="user_password"name="user[password]" type="password"/> <labelfor="user_password_confirmation"]]>Confirmation</label> <inputid="user_password_confirmation" name="user[password_confirmation]"type="password"/> <inputclass="btn btn-large btn-primary"name="commit"type="submit" value="Create my account"/>
</form>
```
## FAQ
1. How does link_to work? What possible arguments does it accept? Answer: See above
2. How do image_tag and other asset helpers work? Where should you put your assets if you want Rails to link to them correctly? Answer: See above
3. How does form_for work? How do you create a form to create a new object? Update an existing one? Answer: See Tyler
4. How do you handle server-side validation errors? Answer: ActiveRecord validations??
5. How do I create a form which posts to a single controller but creates multiple objects without adding loops, etc. to my controller? Answer: Resources: [fields_for] (http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for), [accepts_nested_attributes_for] (http://currentricity.wordpress.com/2011/09/04/the-definitive-guide-to-accepts_nested_attributes_for-a-model-in-rails-3/)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment