Notes to Myself (Rails:Entry#3 - select_tag)
Published: 2021-11-06 21:59:32

My goal here was to associate a movie review with a particular movie via a dropdown list of movie titles.

This is the movie show page:

```ruby
<h1>Movies#show</h1>

<div>
<p>Name: <%= @movie.name %></p>
<p>Year: <%= @movie.year %></p>
<p>Genre: <%= @movie.genre %></p>
<p>Director: <%= @movie.director %></p><br>
Reviews:
<% @movie.reviews.each do |review|%>
<p> "<%= review.post %>"</p>
<% end %>
<button><%= link_to "Add a Review!", new_review_path %></button>
</div>
```
The link_to method has 3 components.

1) the method name "link_to"
2) the element that the user will click on, here the words "Add a Review!" followed by a comma
3) the route path of the link, in this case the "new_review_path" which is the new method in the reviews controller

Once we arrive at the new_review_path we are given this code:

```ruby
  def new
    @review = Review.new
  end
```
...which simply sets up the ability of the new.html.erb page to create a new review.   

This is the new.html.erb form page:

```ruby
<h1>Review this movie</h1>

<%= form_for(@review) do |review| %>
<%= select_tag(:name, options_for_select(Movie.all.collect{ |u| [u.name]})) %>
<p>Post: <%= review.text_area :post %></p>
<p><%= review.submit %></p>
<% end %>
```
I'll gloss over the form_for method since I covered that in a previous blog post, but it is important to note that the select_tag should go inside of the form so that it's parameters can be submitted to the create path.

The select_tag also has 3 components.

1) the method name "select_tag"
2) an argument whose first part is the symbol for the params hash, in this case :name
3) the options_for_select method

The way I've ordered my options_for_select argument is via a class iteration of Movie that returns all of the movies in the database by name.

Once this form is submitted, if you were to inspect the params that is sent to the create method in the Reviews controller, you would see this:

```ruby
 #<ActionController::Parameters {"authenticity_token"=>"g5hKHV_DHRaR6THLAbvsnXAuaK_ZBIoyQKTVLldgaUxOt0eJ60yXOc1qyQDdqRIuNUAIZ7O-RdCb-zeLynjwdg", "name"=>"Jaws", "review"=>{"post"=>"I can't stand it"}, "commit"=>"Create Review", "controller"=>"reviews", "action"=>"create"} permitted: false>
```

Here you'll see that a 🔑  of "name" has been set to the movie title "Jaws", as well as the actual review hash params which contains a key of "post" (the name of the review attribute in the database) which is set to the value "I can't stand it"... the actual review.

So we end up with 2 things.  A review, and a movie.   Both identifiable, and therefore easy to associate in the Review controller's create method.

```ruby
 def create
    review = Review.new(accept_params)
    movie = Movie.find_by(:name => params[:name])
    review.movie_id = movie.id
    review.save
    redirect_to movie_path(movie.id)
  end
```
In the create method I 

-instantiate a new Review
-find a movie by it's title via the params[:name] key
-set the movie id of that movie to the foreign key of my new review
-save the review
-redirect to the show page of this movie

And there you have it!   Only thing to mention:  due to strong params in this program, I defined a private method for both my normal form information and my "imported" form info (the movie names/ids).

```ruby
private

  def accept_params
    params.require(:review).permit(:post)
  end

  def movie_params
    params.require(:movie).permit(:name)
  end
```

If you fail to do this, the review won't be saved in the database because it won't accept the movie_id.