Roads in the rails are very important thing. But for the time being, you can not even pay attention to them. Especially if you use the scaffold command, which automatically writes everything. But at some point it becomes necessary to create non-standard routes. This means it's time to get into the routes.rb file in the config folder of your project.
What are the routes
Routes are a system of routes (paths, urls) on your site. Thanks to routs, we can have beautiful and clear links for users. Entering a link like
mysite.ru/articles/2008/november/13 we will receive all the articles for November 13, 2008, and by link
mysite.ru/shop/shoes we will receive a catalog of shoes from your store. With all this, the directory structure of the site does not change. At any time we can change the routes without touching the location of the files themselves. But for all this to work, we need to set up routes.
To practice
Let's create a test project with which we will shaman. (If you are doing this for the first time, you can discuss in the comments the process of installing the rail and creating the application).
rails routes
cd routes
Okay. The project was created and we entered the working folder. Immediately pounce on routs:
')
rake routes
This command will give you two lines of standard routes.
/:controller/:action/:id
/:controller/:action/:id.:format
This means that any URL will now be parsed by these two rules.
: controller is Controller =). This is a component of
MVC , which most often acts as an intermediary between the View (HTML) and the Model (database, let's say). Further it will be clearer, but most likely you know what it is.
: action is the controller method being called. The controller usually has many methods.
: id - if I explicitly do not specify a ban on creating id, then by default any model (DB table) is created with the id field. Therefore, any element of the model has an id. And when you want to delete / edit / do anything with any specific model element, you are obliged to transfer this id to the controller.
Okay. Let's create a news magazine. For this we need:
- Table news in our database (Model). In the database we will store the title of the article (title), the author of the article (author) and the article itself (article)
- A set of methods for working with the database (controller)
- HTML forms for entering, editing, reading news (Presentation)
We can create it all separately. But now we will simplify our task and use the scaffold function to generate a pack of ready-made files.
./script/generate scaffold Magazine title:string author:string article:text
We have just created all of the above (as well as Helpers, about which some other time). Also, the scaffold team itself created the necessary routes. Once again type the rake routes command and a pile of new routes will fall out
magazines GET / magazines {: controller => "magazines",: action => "index"}
formatted_magazines GET /magazines.:format {: controller => "magazines",: action => "index"}
POST / magazines {: controller => "magazines",: action => "create"}
POST /magazines.:format {: controller => "magazines",: action => "create"}
new_magazine GET / magazines / new {: controller => "magazines",: action => "new"}
formatted_new_magazine GET /magazines/new.:format {: controller => "magazines",: action => "new"}
edit_magazine GET / magazines /: id / edit {: controller => "magazines",: action => "edit"}
formatted_edit_magazine GET /magazines/:id/edit.:format {: controller => "magazines",: action => "edit"}
magazine GET / magazines /: id {: controller => "magazines",: action => "show"}
formatted_magazine GET /magazines/:id.:format {: controller => "magazines",: action => "show"}
PUT / magazines /: id {: controller => "magazines",: action => "update"}
PUT /magazines/:id.:format {: controller => "magazines",: action => "update"}
DELETE / magazines /: id {: controller => "magazines",: action => "destroy"}
DELETE /magazines/:id.:format {: controller => "magazines",: action => "destroy"}
Now we will start the server and play around with the magazine. But first we will create our database and start the migrations.
rake db:create
rake db:migrate
./script/server
Our magazine is now available at
localhost : 3000 / magazines
Create a couple of new articles.
Returning to the table of routes above. The first column is named routes. They are very comfortable. There are several options now to make a link to create a new article. Open app / views / magazines / index.html.erb — this is the view for the index method in the magazines_controller controller.
At the bottom, let's add some code.
<hr> <%= link_to ' ', :action => 'new' %><br /> <%= link_to ' ', '/magazines/new' %><br /> <%= link_to ' ', new_magazine_path %><br /> <%= link_to ' ', new_magazine_url %><br />
The most correct is to use the last two methods. The difference is that url returns the full link (http: // localhost: 3000 / magazines / new), and path is just the path (/ magazines / new). Why is it better to use nominal routs? Named route is a variable, changing which you change all the links that use this route. It is not recommended to write the way by hand in general, if it’s an urge, then it’s better to write: action => 'new' (often there are not enough nominal routes for all cases, therefore this option is very common).
The second column of the table is the query method. One and the same link, but with a different method leads to different methods of the controller. For example, in the same app / views / magazines / index.html.erb:
<%= link_to 'Show', magazine %>
<%= link_to 'Destroy', magazine, :method => :delete %>
The first link executes the default GET request (you can omit it in the link: method =>: get), and the second method is sent: delete. And the link magazine remains the same in both cases.
The third column is actually the links that we get in HTML. The last column is the matching of the links to the controller and method. As already mentioned above, any link can be represented as a pair: controller,: action (well, and sometimes: method).
<% = link_to 'Link to another controller from the magazines controller',: controller => 'blogs',: action => 'show',: id => '1',: method => 'GET'%>
So we get a link to the blog with the index 1. (Here the method: get could not be specified)
<% = link_to 'Link to controller's native method',: action => 'show',: id => '1'%>
Link to the article with the index 1. The controller and the HTTP method in this case is not necessary, since GET is executed by default, and the controller, if not specified, is the same.
Now open the config / routes.rb file (you can delete all the commented text)
map.resources :magazines
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
The first line was inserted by the scaffold team. This line and added us a pack of routes, which we observed above.
If you now just type localhost: 3000 you will be taken to the welcome page. Let's fix it.
map.root :controller => 'magazines'
Now from the public folder, delete index.html and going to
localhost : 3000 you will be taken directly to the right =). In addition, if you view all the routes again (rake routes), you will see a new root named root. And in the menu you can make a link to the “Main” view:
<%= link_to '', root %>
And you will always be able to change the home page, say, to your store map.root: controller => 'shop'
Level II
Actually creating root, you created the first nominal route with your own hands.
Let's create a named
localhost : 3000 / zhurnal route. We do not want bourgeois 'magazines', we want to 'zhurnal'!
map.zhurnal '/klevi_zhurnal/:id', :controller => 'magazines', :id => nil
So, we have created a zhurnal nameplate, whose URL will look like
localhost : 3000 / klevi_zhurnal, and it will receive content from the controller magazines. If we try to read the article now like
localhost : 3000 / klevi_zhurnal / 1 - then we will shrug. Let's make some changes to our route:
map.zhurnal '/klevi_zhurnal/:action/:id', :controller => 'magazines', :action => 'index', :id => nil
What does all of this mean:
- the URL of the form / klevi_zhurnal / will be worked out: controller => 'magazines',: action => 'index',: id => 'nil' - that is, we will get an index page (index.html.erb)
- / klevi_zhurnal / 1 will spit out an error that action '1' does not exist (look at the sequence of passing the argument in the route)
- / klevi_zhurnal / show will say that ID is not specified
- / klevi_zhurnal / show / 1 - will give you an article with ID = 1 (if it exists of course)
- / klevi_zhurnal / edit / 1 - will display the form for editing this article
The truth is now that the links themselves look a bit harder:
Instead of <% = link_to 'All Articles', magazines_path%> will be <% = link_to 'All Articles', zhurnal_path%>
Instead of <% = link_to 'Article number 1', magazine_path ('1')%> will be <% = link_to 'Article number 1', zhurnal_path (: action => 'show',: id => '1')%>
Note that for a better understanding of the routes, a plural / singular system has been introduced:
show all magazines_path articles,
show a separate article: magazine_path.
Devil - not the most correct word in general chose =). If we all called Article:
index => articles_path, show => article_path (: id)
Now let's create a new method.
Open app / controllers / magazines_controller.rb
Add a method there
def random
offset = rand(Magazine.count :all)
@magazine = Magazine.find(:first, :offset => offset)
render :action => 'show'
end
This method simply returns a random article. Let's try calling it:
localhost : 3000 / magazines / random
We get an error - it requires an ID from us. Why? Because the standard route predpolzuet way like: controller /: action /: id.
Let's try to call the route by the rules:
localhost : 3000 / magazines / random / 1230492
Records with this ID does not exist - but everything works! As we in our method do not use ID at all for us and it doesn’t matter what nonsense we write there.
Now let's try to make a correct
localhost : 3000 route / magazines / random /
For this there is an option: collection => {: action =>: HTTP_method}
Our: action is: random, method -: get
we get
map.resources :magazines, :collection => { :random => :get }
now everything works! =)
At this introductory part ends. Further we are waiting for more sophisticated methods of perversion). But not today.
Thank you for the time spent reading the article).
API for those who wishScreencasts by Ryan Bates