In this Ruby Tutorial we will talk about some ActiveRecord techniques you can use when creating, updating and deleting ActiveRecord objects. You will learn an alternative way of creating record by using code block. Probably most of the Rails developers are familiar in creating objects using the following technique
|@product = Product.new
@product.name = “T-shirt”
@product.price = 100.33
Here we are writing a line by line of Ruby code to create an object first, assign it properties and finally save it to the database. You must also have seen we can mass assign bunch of values to the new method using hash for doing the same thing like above
|@product = Product.new( :name => “T-shirt”, :price => 100.33 )
So what we are going to show now is something that sits between the first way of doing and second way of doing. What is nice about first is we get to write Ruby code line by line and what is nice about the second way of creating record is it groups all the attributes in one place. Now what we can do is provide a block of argument to the new method instead of hash
|@product = Product.new do |p|
p.name = “T-shirt”
p.price = 100.33
So now we have the desired way of creating new product, we can write line by line Ruby code. We also have grouped the attributes in one block. Let’s see where the use case of this is. Consider we want to build the application that takes the first name and last name of customer and with that it automatically assigns username to that customer. So the code to achieve this becomes
|customer = Customer.create do |c|
c.first_name = “Bobby”
c.last_name = “Smith”
username = c.first_name
c.username = username << c.last_name
Update multiple records
In past we used to update the record by using update_attribute method and passing parameter we want to update along with the symbol. Take a look at example
But that updates a single attribute. But we also have update_attributes method which allows us to update multiple attributes
|product.update_attributes(:name => “Jeans”, :price => 300)|
We also have an alias for this using product.update. But the problem is this only updates a single record in the database, we probably want to update multiple records in the database. One possible case is using loop statements.
|@products.each do |product|
product.update(:sold => true)
But we have a problem here. Say we have two thousands products, then what we need to do is instantiate all two thousand products in memory and loop through them. This can generate two thousand SQL statements. Now you must be thinking that we should have a solution to this and we do. We can call update_all method on parent for this
|Product.update_all(:sold => true)|
So when I write this code, no matter how much products you have it only generates one SQL statement. The advantages of using this are
- No model is instantiated => no loading any Ruby code just one SQL statement
- Single UPDATE statement
There are also some downside to this because this generates a single SQL statement, we don’t have access to the Ruby code that is inside the model that mean we don’t have access to callbacks and validations.
In most of the cases how we destroy the object was calling destroy method in the object. We have an instance of an object and we call destroy in it. So when it gets executed, it goes to the database, finds that object, creates the SQL statement and destroys it. We also have another method called delete that does the same things.
When you run the destroy method in an object, it is also going to run all the code that is inside the model. But when you run the delete method in an object, it is just going to delete that single object with the help of id that is provided and no ruby code inside the model gets executed. So in this case
- We don’t have model instances
- Single SQL DELETE statement
- No callbacks
So now consider the case when we want to delete multiple records in database just like the case of update. One way is using the loop like before
|@products.each do |product|
@products.each do |product|
We can use either destroy or delete methods to delete the records, but this has the same problem like the update before, if we have two thousand products, it will generate two thousand sql statements.So the better way to delete is by using class methods
product.destroy([33,4,5,6,8]) # Takes array of id
We can also destroy all objects using scope too
Also all these methods are good with delete too but notice that we don’t have any callbacks, no all sql statements and no model instances.
product.delete([33,4,5,6,8]) # Takes array of id
When we have a instance of an object and we call touch method on it, Rails goes to the database and updates the value of updated_at to be the current time.Notice the validations does not happen in this process.
|@product.touch #updates updated_at|
We can also update another column using touch method
Say we have a store and we have products and we can tag products to some tag. We can use the code below to tag a product with object
|@product = Product.find(34)
@tag = Tag.create( :name => “Summer Product”,
:product => @product)
These types of techniques are very useful in ActiveRecord callbacks.
Say we have a blogging application and we have many posts in it. We have a column in post table called is_published? and it is set to boolean value. Then at some point we need to toggle the boolean value in that column. One way to do this is
|@post = Post.find(54)
@post.is_published = false
@post.is_published = ture
But we can a easier and best way of doing this without writing long code using toggle method
|@post = Post.find(12)
Notice, just calling toggle in an object does not save record to database, if you need to save changes to database, use bang(!) operator.
|@post = Post.find(12)
So in this post we discussed about writing efficient codes to manipulate ActiveRecord objects. These methods are not what you should be using straight away but they are in the toolbox you can use whenever the use case fits them.