Helper Methods
Published: 2024-03-01 16:12:35

##**➜ Cleaning up `config/routes.rb`**
```
post("/movies", { :controller => "movies", :action => "create" })
```

- anywhere you see the old `Hash` syntax (`:symbol` keys with hash rockets `=>`): switch to the new `Hash` syntax. Which would be `controller: "movies", action: "create"` 

- next, it is always good to see how many methods are happening on this line, Raghu's convention is that is there no other methods happening, you can leave out the parentheses. so our output would look something like this `get "/movies", controller: "movies", action: "create"`. 

- we can even go further to just take out the controller and action since it is the only method we are placing into the route. remember, the `#` symbol is used to indicate an `Object#method`, which, in this example, is `MoviesController#create`. which would finally leave us with something like this
```
get "/movies" => "movies#create"
```

- for special circumstances like when you are wanting to display the root page of the website, rails has special syntax that allows you to omit the route being displayed, so instead of `  # get("/", { :controller => "movies", :action => "index" })`, you would write it as this `root "movies#index"`. 

##**➜ Route helper methods**
- at the bash prompt, run `rails routes`. the display should look like something similar to this 
```
Prefix Verb   URI Pattern                                Controller#Action
            GET    /                                         movies#index
    movies POST   /movies(.:format)                          movies#create
movies_new GET    /movies/new(.:format)                      movies#new
            GET    /movies(.:format)                         movies#index
            GET    /movies/:id(.:format)                     movies#show
            PATCH  /movies/:id(.:format)                     movies#update
            GET    /movies/:id/edit(.:format)                movies#edit
            DELETE /movies/:id(.:format)                     movies#destroy
```

- `Prefix` means that Rails has defined a method that we can call anywhere in our view templates, controller actions, etc., that will return the path as a string. 

- to test out what exactly this code is doing, move over to the `index.html.erb` page, type in `<%= movies_path %>`, and see what the page renders. you can see that it is displaying the string `"/movies"`. if we were to try others, we can see that `<%= movies_new_path %>` refresh the change, and `/movies` renders `"/movies/new"`. Following this pattern, `<%= root_path %>` just renders `"/"`. 

- `movies` and `movies_new` are static routes, without dynamic ID numbers in the path, so Rails just puts the segments together and gives you the method. But, for all the rest of the routes that do contain `:id`, there are no methods defined yet. We get to define those methods ourselves!
##**➜ Creating our own route helper methods**
```
get "/movies/:id" => "movies#show", get "/movies/:id" => "movies#show", as: :details
```

- say for the one above, `"/movies/:id"` has `:id` within the route, so we have to properly define it after the route, just like we are doing **above**, the `as: :details` part of the route is us defining a specific method, we can then transition back into the `index.html.erb` file and define our route like so `<%= details_path %>`. 

- if we see what this provides us with it will be an error `No route matches {:action=>"show", :controller=>"movies"}, missing required keys: {:id}`. this is because it is a dynamic route, so rails cant produce a route unless you tell it what to put in the path! 

- say if we were to put `(42)` within this ruby syntax helper method, it would be able to display the route with the `:id` being `(42)`. 

- you can also change the embedded ruby method to `details_url(42)`, then you will be able to see the full url of the app, including the path, this allows you to see fully qualified url's. this means you dont need to hardcode anything because it will be able to full run on any persons own personal web browser. 

- now we are going to be placing them into the normal conventions that every ruby developers use. such as 

```
get "/movies/new" => "movies#new", as: :new_movie
get "/movies/:id/edit" => "movies#edit", as: :edit_movie
```

- we however dont need to define the helper methods for delete or patch 
```
patch "/movies/:id" => "movies#update"
delete "/movies/:id" => "movies#destroy"
```
##**➜ implementing helper methods**
- Now we are going to be taking those helper methods and placing them into the rest of our code, so these are going to work the same way as routes, where instead of having the routes path and then placing the variable into it with ruby `<%= a_movie.id %>` like this, we will change it to something like below...
```
<form action="<%= movie_path(@the_movie.id) %>" method="post" data-turbo="false">
  <input name="authenticity_token" value="<%= form_authenticity_token %>" type="hidden">
```
- another point, since we are taking the specific movie id for the route, we can use ruby convention and just always assume that that is what it will naturally grab specifically unless we say otherwise `action="<%= movie_path(@the_movie) %>"`

- say we are implementing them into our controllers for redirection, for this piece of code for example...
```
if @the_movie.valid?
      @the_movie.save
      redirect_to("/movies", { :notice => "Movie created successfully." })
    else
      render template: "movies/new"
    end
```

- we can instead change `"/movies"` to `movies_url`, since we want to specifically route them to a url and not use the path name `/movies`

##**➜ Creating forms with helper methods**

```
<%= form_with(url: movies_path) do %>
  <div>
    <!--    <label for="title_box">
      Title
    </label>-->
    <%= label_tag :title_box, "Title" %>
    <!--<input type="text" id="title_box" name="query_title" value="<%#= @the_movie.title %>">-->
    <%= text_field_tag :query_title, @the_movie.title, { id: "title_box" } %>
  </div>

  <div>
    <!--<label for="description_box">
      Description
    </label>-->
    <%= label_tag :description_box, "Description" %>
<!--    <textarea id="description_box" name="query_description" rows="3"><%#= @the_movie.description %></textarea>\ -->
    <%= text_area_tag :query_description, @the_movie.description, id: "description_box", rows: 3 %>
  </div>    

 <!-- <button>
    Create Movie
  </button>-->
    <%= button_tag "Button"%>
<% end %>
```

- here you can see the before and after of placing in tags to our forms, and below is a much more organized way to look at it
```
<%= form_with(url: movies_path) do %>
  <div>
    <%= label_tag :title_box, "Title" %>
    <%= text_field_tag :query_title, @the_movie.title, { id: "title_box" } %>
  </div>

  <div>
    <%= label_tag :description_box, "Description" %>
    <%= text_area_tag :query_description, @the_movie.description, id: "description_box", rows: 3 %>
  </div>    

    <%= button_tag "Button"%>
<% end %>
```
##**➜ `find_by` method**

- what we have been practicing before has led us to this moment where we will be totally deducing our 3 steps to get an `ActiveRecord` instance (a single row of a table, compared to an `ActiveRecord:Relation` (which is many rows of a table. 

- in the beginning of learning ruby, we had something very similar to this setup in our code... 
```
def show
    the_id = params.fetch(:id) # FIRST we get the ID

    matching_movies = Movie.where(id: the_id) # THEN we get the set of matching rows (ActiveRecord:Relation)

    @the_movie = matching_movies.first # FINALLY we get one instance of ActiveRecord, or one row
  end
```

- now we are presented with something very similar to this, essentially reducing whatever we started with to a more simplified version, such as this...
```
def show
    @the_movie = Movie.where(id: params.fetch(:id)).first
  end
```

- **now, finally we are going to be stripping that even more to a better more conventional version of this piece of code, something using the `.find_by` method. it is essentially the same thing as where, except that is automatically returns the `.first` record given in a collection without having to explicitly say that.**
```
  def show
    @the_movie = Movie.find_by(id: params.fetch(:id)) 
  end
```
or _shorter_
```
def show
    @the_movie = Movie.find(params.fetch(:id))
  end
```
>important to note here that the `.find()` method only takes an integer argument and is specifically for finding ID's in the ID column table

- now we can accurately and effectively search for what we need without using lines and lines of code as we were doing before. 

##**➜ Creating a checkbox form**
###getting an array with checkbox
```
<form>
  <label>Red</label>
   <input type="checkbox" name="zebra[]" value="red"> 

  <label>Blue</label>
  <input type="checkbox" name="zebra[]" value="blue"> 
</form> 
```
>output looks something like this 
```
zebra["red", "blue"]
```
###getting an array with hashes with checkbox
```
<form>
  <label>Red</label>
   <input type="checkbox" name="zebra[giraffe]" value="red"> 

  <label>Blue</label>
  <input type="checkbox" name="zebra[elephant]" value="blue"> 
</form> 
```
>output looks something like this 
```
zebra["giraffe" => "red", "elephant" => "blue"]
```
##**➜ Mass assignment with forms**
```
<%= form_with(model: @movie, data: { turbo: false }) do |form| %>
  <div>
    <%= form.label :title %>

    <%= form.text_field :title %>
  </div>

  <div>
    <%= form.label :description %>

    <%= form.text_area :description, { rows: 3 } %>
  </div>

  <%= form.button %>
<% end %>
```
##**➜ Adding method**

- This movie_params is a good tool to understand and takes away the need to write in a new table over and over again when making it cause you would just add it in one place and then it could be added everywhere. 
```
def movie_params
    params.require(:movie).permit(:title, :description, :image_url, :director_id)
  end
```
##**➜ partial view templates**

- You can only add a partial to a big, not a big to a big or a big to a partial. this helps up organize our code into more folders and shorter lines so we are not overwhelmed by how many lines could be for each page. 
```
<%= render "shared/flash_messages", locals: { person: "Alice" }%>
```
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aghac7pbv3y1cec8y30g.png)

- could be good for explaining name for each user in the top corner 

- in the file youre displaying 
```
<%= render partial: "movies/form", locals: { foo: @the_movie} %>
```

- in the partial 
```
<% foo.errors.full_messages.each do |message| %>
  <p style="color: red;"><%= message %></p>
<% end %>
```