Models in Rails use the singular name, and their corresponding table in the database uses the plural name. Rails provides a model generator that most Rails developers use to create new models. To create a new model, run this command in your terminal:
$ bin/rails generate model Article title:string text:text
With this command, we tell Rails that we want an Article model with a title attribute of the string type and a text attribute of the text type. These attributes are automatically added to the articles table and bound to the Article model.
Rails will create a series of files in response. Right now we are only interested in app/models/article.rb and db/migrate/20140120191729_create_articles.rb (your name may be slightly different). The latter is responsible for creating the database structure, which is why we will look at it further.
TIP: Active Record is smart enough to automatically associate column names with model attributes, which means you don’t have to declare attributes inside Rails models, Active Record does it automatically.
Running the migration
As you have seen, bin/rails generate model created a database migration file in the db/migrate directory. Migrations are a Ruby class designed to make it easy to create and modify database tables. Rails uses rake commands to run migrations, and it is possible to undo a migration after it has been applied to your database. The migration filename includes a timestamp to make sure they run in the order in which they were created.
If you look into the db/migrate/YYYYMMDDHHMMSS_create_articles.rb file (remember, your file has a slightly different name), here’s what you’ll find:
class CreateArticles < ActiveRecord::Migration[5.0] def change create_table :articles do |t| t.string :title t.text :text t.timestamps end end end
This migration creates a change method that is called when this migration is run. The action defined in this migration is also reversible, which means that Rails knows how to undo the changes made by this migration in case you decide to undo them later. When you run this migration, it will create an articles table with a string column and a text column. It will also create two timestamp fields to keep track of when the article was created and updated.
TIP: For details about Rails migrations, see the Active Record Migrations guide.
Now we need to use the bin/rails command to run the migration:
Rails will run this migration command and report that it has created the Articles table.
== CreateArticles: migrating =========================================== =====
== CreateArticles: migrated (0.0020s) ========================================
NOTE: Since you are running in the development environment by default, this command will apply to the database defined in the development section of your config/database.yml file. If you want to run migrations in another environment, such as production, you must explicitly pass it when you call the command: bin/rails db:migrate RAILS_ENV=production.
Saving data in the controller
Back to the ArticlesController, we need to modify the create action to use the new Article model to save data to the database. Open app/controllers/articles_controller.rb and modify the create action as follows:
def create @article = Article.new(params[:article]) @article.save redirect_to @article end
Here’s what’s going on: each Rails model can be initialized with the appropriate attributes, which will automatically be bound to the appropriate columns in the database. In the first line, we do just that (remember that params[:article] contains the attributes we are interested in). Then @article.save is responsible for saving the model to the database. Finally, we redirect the user to the show action, which we will define later.
TIP: You may be wondering why the A in Article.new is capitalized when all other article links in this guide use lowercase. In this context, we are referring to a class named Article, which is defined in app/models/article.rb. Class names in Ruby must start with a capital letter.
TIP: As we’ll see later, @article.save returns a boolean indicating whether the model has been saved or not.
If you now go to localhost:3000/articles/new, you should almost be able to create a new article. Try it! You should get an error that looks like this:
Forbidden attributes for new article
Rails has a number of safeguards to help you write secure applications, and you just came across one of them. It’s called strong parameters and it requires us to tell Rails which parameters are allowed to be passed to our controller actions.
Why do you need to worry about this? The ability to take and automatically assign all controller parameters to your model will make the programmer’s job easier, but this convenience also allows for malicious use. What if the request to the server was specifically crafted as a new article form submission, but also includes additional fields that break the integrity of your application? They will be ‘massively assigned’ to your model and then to the database among the normal data – potentially breaking your application, or worse.
We need to whitelist our controller parameters to prevent erroneous mass assignment. In this case, we want to both allow and require the title and text parameters to be used correctly in create. The syntax for this is represented by the require and permit methods. The change affects one line in the create action:
@article = Article.new(params.require(:article).permit(:title, :text))
This is often moved to a separate method so that it can be reused in multiple actions of the same controller, such as create and update. A method is often made private (no longer associated with bulk assignment) to ensure that it cannot be called outside of the intended context. Here is the result:
def create @article = Article.new(article_params) @article.save redirect_to @article end private def article_params params.require(:article).permit(:title, :text) end
TIP: See this article on Strong Parameters for details.
If the form is submitted again, Rails will report a show action not found. We don’t need this anymore, so let’s add a show action before that.
As you saw in the output of bin/rails routes, the route for the show action is:
article GET /articles/:id(.:format) articles#show
The :id special syntax tells rails that this route expects an :id parameter, which in our case will be the article ID.
As before, we need a show action in app/controllers/articles_controller.rb and its corresponding view.
NOTE: It is a common practice to put standard CRUD actions in each controller in the following order: index, show, new, edit, create, update and destroy. You can use any order you want, but remember that these are public methods; as mentioned earlier in this guide, they should be placed before the private visibility definition in the controller.