We will conquer Ruby together! Drop thirteen
Today we will get acquainted with such a powerful and useful Ruby tool and RoR component as Active Record. As part of RoR, we know Active Record from the first step of articles on rails (something this series didn’t do very well, though). Consider the practical application of the component in Ruby, which is very useful in RoR.
Active Record adheres to the principles of ORM : databases can be represented as object-oriented code, where tables are classes, table rows are objects, and fields are object attributes. However, Active Record is different from other ORM libraries, for example,
When you create a new record in the database, update the existing one or simply read the data, everything goes in three steps: creating an Active Record object, accessing and manipulating the attributes of the object, and saving the attributes as records in the database.
As usual in the Ruby installation - a trifling matter, it suffices to establish the necessary jam:
Let's start with such a table . First of all, connect to the database:
As you can see, for this you need to pass the
In accordance with the table, we create an inheritor class:
It is worth paying special attention to the name of the class. As usual, the principle of conventions over configuration works here, according to which the name of the table is plural, the name of the class is singular. You can, of course, circumvent this limitation, but you should not do this - work in the Ruby / Rails way, and you will understand how convenient this is.
So, as we know, in order to create a record in a table, we must work with Ruby objects. To create a new row in the database
This is where we see one of Ruby's key advantages - metaprogramming. On the fly, methods were created for us, with the same name as the table columns, for editing instance attributes. Very convenient, but this is only the beginning, then more. However, this is only an instance of the class, the table has not changed (as mentioned above). In order to “synchronize” an instance with a table by creating a new row, we use the method
Another way to record:
We learned to save records, now we need to extract them. We understand that in this case we must create an instance of the class and fill it with attributes from the table row. In fact, it is easier. If we know the
Pretty trivial, but what if we want to search by columns / attributes? Here Ruby's metaprogramming framework comes to the rescue again - we use dynamic search methods:
This is a small piece of magic that Active Record provides us with - again, the methods were generated for us on the fly. I think that the structure of their name is understandable. Cool example:
And in this case, the name of the method speaks for itself: “find or create a username”. Accordingly, if during the search an element (we say an element - we mean a table row, but, in fact, it is) that falls under the search condition is not found, then it will be created and saved to the table (
So, we created the required instance / row, found it, now we look at how to update the data and delete it completely:
It is worth noting here that despite the fact that we deleted the row from the database, the instance continues to exist read-only, until the instance itself is deleted or goes out of scope (scope is a separate topic).
Communication between objects is not only an incredibly important part of Active Record functionality, it is simply necessary in real applications. There are several types of connections, we will consider one.
Now we want to bind a specific group to each user, such as Administrator or Guest. Let's start by creating a table
We must define the connection in the class
Now we have one-way communication - the account knows that it has a group, and the group does not know about its accounts. Let's create an administrator group and assign an account to it:
As you can see, a new method has appeared for the Account class, writing a group to it. We just “equated” the attribute (actually not the attribute, but for the end user it looks like this) of the account to the entire instance of the group, Active Record understands this by doing what we need.
Here is an introduction to this powerful system. First of all, it, of course, will be used when working with web applications, Rails in particular. If you have a desire, then we can go deeper into Active Record or, for example, Rake. As usual - comments and comments are welcomed at the highest level;)
Active Record adheres to the principles of ORM : databases can be represented as object-oriented code, where tables are classes, table rows are objects, and fields are object attributes. However, Active Record is different from other ORM libraries, for example,
Hibernate
fromJava
, because there is no need for an initial configuration - everything works out of the box. Active Record is written in pure Ruby, which allows us to work with it like a regular class: use inheritance, rewrite methods, use metaprogramming, etc. Yes, the attributes of an object are filled in most cases using SQL queries and exactly the same attributes are written back to table. But all that happens between these two processes is the usual work with the Ruby object. It is worth understanding the “separateness” of the existence of database records and Ruby objects: sometimes the database will differ from the Ruby class.When you create a new record in the database, update the existing one or simply read the data, everything goes in three steps: creating an Active Record object, accessing and manipulating the attributes of the object, and saving the attributes as records in the database.
Setting Active Record
As usual in the Ruby installation - a trifling matter, it suffices to establish the necessary jam:
gem install activerecord
. Connecting to the database is done using adapters, most of which are already built-in ( DB2, Firebird, FrontBase, MySQL, Open-Base, Oracle, PostgreSQL, SQLite, SQL Server
and Sybase
), you only need to transfer the parameters for connecting to the database. You should also make sure that you have installed / running the database server and installed the correct jam ( mysql
or sqlite3-ruby
, for example).In use
Let's start with such a table . First of all, connect to the database:
Accounts:
id (integer; auto-incremented; primary key)
username (text)
password (text)
require "rubygems"
require "activerecord"
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "user",
:password => "pass",
:database => "project_development")
As you can see, for this you need to pass the
establish_connection
parameters in the form of a hash to the method . For SQLite, only :adapter => "sqlite"
and are needed :database
. In accordance with the table, we create an inheritor class:
Class Account < ActiveRecord::Base
end
It is worth paying special attention to the name of the class. As usual, the principle of conventions over configuration works here, according to which the name of the table is plural, the name of the class is singular. You can, of course, circumvent this limitation, but you should not do this - work in the Ruby / Rails way, and you will understand how convenient this is.
So, as we know, in order to create a record in a table, we must work with Ruby objects. To create a new row in the database
Accounts
, create an instance of the class Account
using the standard method new
:acc1 = Account.new
acc1.username = "maxelc"
acc1.password = "maxspassword"
This is where we see one of Ruby's key advantages - metaprogramming. On the fly, methods were created for us, with the same name as the table columns, for editing instance attributes. Very convenient, but this is only the beginning, then more. However, this is only an instance of the class, the table has not changed (as mentioned above). In order to “synchronize” an instance with a table by creating a new row, we use the method
save
:acc1.save
Another way to record:
acc2 = Account.new(
:username => "hbuser",
:password => "habrapass")
acc2.save
We learned to save records, now we need to extract them. We understand that in this case we must create an instance of the class and fill it with attributes from the table row. In fact, it is easier. If we know the
id
lines, then we use the built-in (core) method find
:result1 = Account.find(1)
Pretty trivial, but what if we want to search by columns / attributes? Here Ruby's metaprogramming framework comes to the rescue again - we use dynamic search methods:
result2 = Account.find_by_username("hbuser")
This is a small piece of magic that Active Record provides us with - again, the methods were generated for us on the fly. I think that the structure of their name is understandable. Cool example:
result3 = Account.find_or_create_by_username("superuser")
And in this case, the name of the method speaks for itself: “find or create a username”. Accordingly, if during the search an element (we say an element - we mean a table row, but, in fact, it is) that falls under the search condition is not found, then it will be created and saved to the table (
save
not needed in this case). So, we created the required instance / row, found it, now we look at how to update the data and delete it completely:
Account.update(1, {:password => 'newpass'})
puts "запись сохранена"
Account.delete(2)
It is worth noting here that despite the fact that we deleted the row from the database, the instance continues to exist read-only, until the instance itself is deleted or goes out of scope (scope is a separate topic).
Active Record Links
Communication between objects is not only an incredibly important part of Active Record functionality, it is simply necessary in real applications. There are several types of connections, we will consider one.
Now we want to bind a specific group to each user, such as Administrator or Guest. Let's start by creating a table
Groups
containing id
and name
(groups). You also need to add a Accounts
new column group_id
to the table for use as a foreign key (naming conventions work again). In our case, you can imagine the relationship as "each account belongs to a role." For this type of relationship, the method is used belongs_to
. But first, create a new class for Groups
in our script:class Group < ActiveRecord::Base
end
We must define the connection in the class
Account
by adding the class as follows:class Account < ActiveRecord::Base
belongs_to :group
end
Now we have one-way communication - the account knows that it has a group, and the group does not know about its accounts. Let's create an administrator group and assign an account to it:
admin_group = Group.find_or_create_by_name("admin")
account.group = admin_group
account.save
As you can see, a new method has appeared for the Account class, writing a group to it. We just “equated” the attribute (actually not the attribute, but for the end user it looks like this) of the account to the entire instance of the group, Active Record understands this by doing what we need.
Epilogue
Here is an introduction to this powerful system. First of all, it, of course, will be used when working with web applications, Rails in particular. If you have a desire, then we can go deeper into Active Record or, for example, Rake. As usual - comments and comments are welcomed at the highest level;)