Deploy apps to servers that you own and control.
Application monitoring that helps developers get it done.
Now that we know how to define schemas for our tables, let’s focus on inserting records into these tables using the Active Record interface.
Jumping back into an IRB session playground, I now have a more realistic posts table with a title and body column. Let’s set this up, create our posts table, and look at how we can create a new post.
The most common method to create a new record is the create method. We add this 'bang', the exclamation point and we call it on our Post model and pass in values like this:
Post.create!(title: "title one", body: "some text")
When we run this, the logs reveal three SQL queries being executed:
Active Record wraps inserts in a transaction to ensure data integrity. This guarantees that records are durably and safely written to the database, preventing incomplete writes or corruption.
Looking at the INSERT INTO statement, we can see:
Using bind parameters in SQL queries provides a performance boost by:
Once the data is inserted, SQLite returns the id of the newly created record, which Active Record assigns to the Post instance.
We see that this method, the create method, returns an instance of our post class.
post1
post1 is our new post record. The final detail worth noting is that at the end of this equery have have this RETURNING "id" clause. SQLite is going to return a subset of columns from this insert into Active Record. All I really need is the ID. What was the auto incremented primary key that the engine used to fill in this value? We want our actual post instance to have that value when we look at it.
The fact that it only returns ID is in fact the source of the problem that we saw last time, where a time column, when we were originally looking with our post instance had a specified year, month, and day though in the database it had been resolved into just January 1, 2000.
Unfortunately, as of right now, there is no way to force active record to return a different set of columns when you're using the create method. Hopefully this is something that will be addressed in the future.
Active Record provides two variations of the create method:
post = Post.create!(title: nil) # Throws an error if validation fails
post = Post.create(title: nil) # Returns `false` instead of raising an error
Only use the bare version if you're 100% certain of what you need and you know you only need the boolean response.
Another way to create records is by initializing a Post object first and saving it later:
post3 = Post.new(title: "title two", body: "some more text")
post3 # Returns an in-memory Ruby object without an id or timestamps.
No SQL queries have been run yet. We can make changes to this object:
post3.title = "Updated"
Again no SQL queries have been run. At any point we can call save on this object and this will execute a SQL query.
post3.save!
This method is useful when you need to modify data before saving it or when creating records in multiple steps.
By using prepared statements and reusing the same SQL query shape, SQLite does not have to recompile the SQL query each time, leading to faster repeated insertions. This approach:
With Active Record there are 3 ways you can create records.
In the next video, we’ll explore additional ways to insert records and discuss when to use different Active Record methods for creating records in real-world Rails applications.