ABOUT ARI

  • Ari 0 reviews

Overview

In this post 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

@product.save

 

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 )

@product.save

 

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

end

@product.save

 

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[0]

   c.username = username << c.last_name

End

customer.save

 

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

 

product.update_attribute(:name, “jeans”)

 

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)

end

 

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.

 

Delete records

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.

 

product.destroy

product.delete

 

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|

 product.destroy

end

 

@products.each do |product|

 product.delete

end

 

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)

product.destroy([33,4,5,6,8]) # Takes array of id

 

We can also destroy all objects using scope too

 

product.outdated.destroy_all

 

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)

product.delete([33,4,5,6,8]) # Takes array of id

product.outdated.delete_all

 

Touch record

 

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

 

@product.touch(:sold_at)

 

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.

 

Toggle Attributes

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)

 

if @post.is_published?

@post.is_published = false

else

@post.is_published = ture

end

 

But we can a easier and best way of doing this without writing long code using toggle method

 

@post = Post.find(12)

 

@post.toggle(:is_published?)

 

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)

 

@post.toggle!(:is_published?)

 

 

ActiveRecord Callbacks

Callbacks are those methods that can be called on an object that gets called when it is created, updated and destroyed. They can be called during the object’s life cycle. For instance if you want to save only names in database in lowercase, you need to use callbacks before saving to database. One of the example of callbacks is

 

class User < ApplicationRecord

 validates :login, :email, presence: true

 before_create do

   self.name = login.capitalize if name.blank?

 end

end

 

If you want to learn more about callbacks, the link is here

 

ActiveRecord Validations

Validations are added in ActiveModel in Rails, to ensure only the data in correct structure are saved to database. For example, we can use validation in our model to ensure the full name of a person is not less than 4 characters long and greater than 25 characters. The example is also in the above example where we ensured, for a user to login he must enter email.

 

ActiveRecord Scopes

Scope is a method for retrieving and querying objects. Using scopes we can narrow down the database query.Let’s take an example using scope in model.

 

class Jeans < ActiveRecord::Base
 scope :blue, -> { where(color: ‘blue’) }
 scope :dry_clean_only, -> { joins(:washing_instructions).where(‘washing_instructions.dry_clean_only = ?’, true) }
end

 

 

Here we have two scopes and they are helping us to narrow down the query and help to return particular result.

 

Regular Expressions for Validation

Regular expressions are very fast and efficient way of validations if used correctly. If you don’t have much confidence, you better not use it. For example, to validate the pattern of email we can use following regular expression in our model

 

class Person

 include ActiveModel::Validations

 validates :name, presence: true

 validates_format_of :email, with: /\A([^\s]+)((?:[-a-z0-9]\.)[a-z]{2,})\z/i

 validates! :token, presence: true

end

 

 

Conclusion

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.

Project History & Review (0)

There are no projects found.

INFO

  • Member Sinced: December 26, 2013
  • Address:
  • Total spent: $0.00
  • Project posted: 0
  • Complete project(s): 0