Rails is our web framework.
ActiveRecord
)
belongs_to
, has_many
, has_many :through
ERB
Find The Ruby on Rails Tutorial in our library. It should be the 7th edition that works with Rails 7.0.
Work through the following chapters and skip the rest. Also skip deployment to Heroku and upload to AWS S3 everywhere.
1 From zero to deploy
Introduction
1.1 Up and running
1.2 The first application
2 A toy app
All sections
3 Mostly static pages
All sections
5 Filling in the layout
All sections
6 Modeling users
All sections
7 Sign up
Introduction
7.1 Showing users
7.2 Signup form
7.3 Unsuccessful signups
7.4 Successful signups
7.6 Conclusion
8 Basic login
All chapters
13 User microposts
All chapters except 13.4.4 Image upload in production
For each chapter:
We will also be using a different development environment than the book suggests. Deviate from the following instructions:
ruby -v
.Please note that the dependencies Hotwire, Turbo and Stimulus are not part of our usual stack. Don't spend too much time trying to understand how they work exactly.
We want to take what learned from the tutorial and apply it to our own app. In this exercise we will write a Rails app that manages a list of movies and a list of actors. We will call this app "MovieDB" in subsequent cards. Skim the README file of the project if you have not done that already.
Your MovieDB should deliver the following requirements:
For our MovieDB we will use Rails 7 without Turbolinks. You should already have forked the movie-db-base
application in a previous card. Build your MovieDB on top of this fork.
Hint
- Use a join model Show archive.org snapshot like
Role
orCasting
to associate actors with the movies they star in. A movie's show view should link to associated actors. An actor's show view should link to associated movies.- We recommend to build the views from scratch, without scaffolding. If you do use scaffolding, you must understand every line of the generated code. Also delete any generated code that is not required for your application.
- The movie's show view could just render the castings partial. This is sufficient to fulfill the corresponding requirement above (that a user should be able to create a movie/actor association on the movie's show view.)
- The "release year" field should be stored as an
integer
column in the database. Don't get confused by the use oftext_field
below.
Refactor your MovieDB controllers to the pattern of our default controller implementation (without caching and pagination).
In this exercise we take a closer look at how the HTML forms produced by Rails helpers, and how user input in those forms is sent over the wire and saved to your database.
Tip
We are not going to keep changes from this exercise. Before you start, make sure all changes from previous exercises and commited and pushed. We will discard any changes at the end of this exercise.
Take a look at your view to create a new movie, app/views/movies/new.erb
. It will look something like this:
<%= form_for @movie do |form| %>
<%= form.text_field :title %>
<%= form.text_field :release_year %>
<%= form.submit %>
<% end %>
Your actual view will be longer. For the sake of this example we only look at a minimal subset.
Now go to http://localhost:3000/movies/new to access that view. Right-click into your form and select Inspect. You should see the HTML generated by your view. It will look something like this:
<form action="/movies">
<input type="text" name="movie[title]">
<input type="text" name="movie[release_year]">
<input type="submit" name="commit" value="Save movie"></button>
</form>
Again your actual HTML will be longer.
Note the peculiar name
attributes of the inputs, e.g. movie[title]
. This name was chosen automatically by the form.text_field
helper, and it will be helpful later.
Now open the Network tab in your developer console (CTRL+Shift+I
in Chrome).
Fill out the movie. Use the title Sunshine
and the release year 2007
. Submit the form.
In the network tab you will see the HTTP request to save the movie. Select the request from the list and go to the sub-tab Payload. You should see your request's payload as a list of key/value pairs:
movie[title] Sunshine
movie[release_year] 2007
commit Save movie
Now change your MoviesController#create
method so it prints out the params
that Rails sees. For this we comment out the code that was creating the movie and render the params
object:
def create
# @movie = Movie.new
# @movie.attributes = params[:movie]
# if @movie.save
# redirect_to @movie
# else
# render 'new'
# end
render plain: params.inspect
end
Note that #inspect
returns a human-readable representation of an object. All Ruby objects implement this.
Submit the new movie form again and you should see something like this:
{
'controller' => 'movies',
'action_name' => 'create',
'movie' => { 'title' => 'Sunshine', 'release_year' => '2007' },
'commit' => 'Save movie'
}
Note how Rails has used the square brackets in the payload keys to group all movie attributes into one sub-hash, params['movie']
.
Let's take a look at only the movie-related attributes:
def create
# @movie = Movie.new
# @movie.attributes = params[:movie]
# if @movie.save
# redirect_to @movie
# else
# render 'new'
# end
render plain: params[:movie].inspect
end
Note that we can use either params[:movie]
(symbol key) or params['movie']
(string key) and get the same value. This is a peculiarity of the params
hash, other Ruby hashes don't share this behavior.
Submit the new movie form again and you should see something like this:
{ 'title' => 'Sunshine', 'release_year' => '2007' }
Restore the original implementation of MoviesController#create
. It probably has a line like this somewhere:
@movie.attributes = params[:movie]
We now know that this expands to the following:
@movie.attributes = { 'title' => 'Sunshine', 'release_year' => '2007' }
And this is a shortcut to set individiual attributes in separate lines:
@movie.title = 'Sunshine'
@movie.release_year = '2007'
Hopefully this clarifies how form values are assigned to your model records.
When you're done with this exercises, discard all changes:
git reset --hard