Sprint 4: Ruby on Rails - Helper Methods for Routes and Links
Published: 2024-03-02 02:06:06

Basics are basics. Once we get the hang of the underlying mechanisms that make Ruby ideal for learning and development, we can start learning the many helper methods that automate these functions. 

This post will focus on the many helper methods we can to avoid dealing with unnecessary bugs. 

----------------------------------------------------------------

Part 1: Helper methods for naming routes and links

Naming routes: there are several levels to utilizing helper methods here. Depending on your comfortability with helper methods, the level of abstraction increases or decreases.

-Level 1 - new Hash syntax + optional parenthesis:

A route like this:
```ruby
get("/", { :controller => "movies", :action => "index"})
get("/movies", { :controller => "movies", :action => "create })
```

can be transformed into: 
```ruby
root "movies#index"
get "/movies" => "movies#create"
```

-Level 2 - Prefix methods + _path and _url helper methods:

Using the "as:" keyword, we can define prefixes for our routes that we can reference = DRY principle.
```ruby
Rails.application.routes.draw do
  root "movies#index"

  # CREATE
  post "/movies" => "movies#create", as: :movies
  get "/movies/new" => "movies#new", as: :new_movie
          
  # READ
  get "/movies" => "movies#index"
  get "/movies/:id" => "movies#show", as: :movie
  
  # UPDATE
  patch "/movies/:id" => "movies#update"
  get "/movies/:id/edit" => "movies#edit", as: :edit_movie
  
  # DELETE
  delete "/movies/:id" => "movies#destroy"

end
```
NOTE: we only need to define a prefix ONCE if the routes are identical but the HTTP Verb is DIFFERENT. Rails is smart enough to know which route to take as long as the proper HTTP Verb is defined.

NOTE 2: in order to reference these paths, we can either use <prefix_name>_url OR <prefix_name>_path. Use _url for *fully qualified URL*. 

Example:
```ruby
<div>
   <a href="<%= edit_movie_path(@the_movie) %>">
          Edit movie
   </a>
</div>
```
NOTE 3: when we're dealing with dynamic paths, we can pass the ActiveRecord Object like an argument in the _path() and Rails is smart enough to know to look for the "id" column.

-Level 3 - resources: we completely abstract the routes away because the CRUD functions are so common. Resources will define all the routes and helper methods we generally need - following convention.

```ruby
root "movies#index"
resources :movies
```

----------------------------------------------------------------

Part 2: Shortening template names

Level 1 - shortening render template: when passing render as a SINGLE argument, Rails assumes its a view template.

Therefore, a code like this:
```ruby
def new
    @the_movie = Movie.new

    render template: "movies/new"
end
```

can be shortened to:
```ruby
def new
    @the_movie = Movie.new

    render "movies/new"
end
```

Level 2 - remove it entirely: if the folder name that contains the view templates match the Controller name + the view template name matches the action name, Rails can just assume which view template is being referenced.

```ruby
def new
    @the_movie = Movie.new
end
```

----------------------------------------------------------------

Part 3: link_to 

Level 1 - using link_to to create an < a > tag. 

```ruby
<!-- <a class="navbar-brand" href="/">Helper Methods 3</a> -->

     <%= link_to "Helper Methods 3", root_path, class: "navbar-brand" %>
```
Level 2 - using link_to but ONLY passing the ActiveRecord Object itself for the route: behind the scenes Rails takes the class of the Object then uses .downcase before doing a + "_url".

```ruby
<%= link_to "Show details", movie_path(a_movie) %>

<%= link_to "Show details", a_movie %>
```

-NOTE: in the example above, both < a > tags will work identically. The assumption that Rails make is that: a_movie.class.downcase + "_url" = movie_url

-Example 2 - dealing with the delete verb:

```ruby
<%= link_to "Delete Movie", @movie, data: { turbo_method: :delete } %>
```

CY@