12
Rolling with Rails 2.0 - The First Full Tutorial - Part 1
on December 12, 2007
for brazilians: click here.
I am very happy to see that my Rails 2.0 Screencast was very well received. More than 1,500 unique visitors watched it. The idea was to showcase Rails 2.0 very fast, showing what is possible to do in less than 30 min.
Now, I will break that video down into its main pieces and create the very first full featured step-by-step tutorial around Rails 2.0.
Like any other tutorial, it doesn’t cover 100% of Rails 2.0, just some of its main features packed in a cohesive application. I recommend checking out Peepcode’s Rails2 PDF and Ryan Bates Railscasts.com for more details.
This is a 2 part tutorial, for Part 2, click here. And for the full source codes of this tutorial, get it here.
Let’s get started!
Recognizing the Environment
This tutorial is geared towards those who already have some knowledge of Rails 1.2. Please refer to the many great Rails tutorials around 1.2 available in the Internet world-wide.
The first think you have to do is update your gems:
sudo gem install rails --include-dependencies
You may probably need to update RubyGems as well:
sudo gem update --system
First things first. Let’s create a new Rails application:
rails blog
This will create our usual Rails folder structure. The first thing to notice is the environment: we now have this main structure:
- config/environment.rb
- config/initializers/inflections.rb
- config/initializers/mime_types.rb
Everything that inside the config/initializers folder is loaded at the same time the original environment.rb is, and that’s because when you’re using several different plugins and gems in your project, the environment.rb file tends to become cluttered and difficult to maintain. Now we have an easy way to modularize our configuration.
Database
The second thing that we have to do is configure our databases. This is done the same way as before at config/database.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
development: adapter: mysql encoding: utf8 database: blog_development username: root password: root socket: /opt/local/var/run/mysql5/mysqld.sock test: adapter: mysql encoding: utf8 database: blog_test username: root password: root socket: /opt/local/var/run/mysql5/mysqld.sock production: adapter: mysql encoding: utf8 database: blog_production username: root password: root socket: /opt/local/var/run/mysql5/mysqld.sock |
Notice that now you have a ‘encoding’ options that’s set to UTF8 by default. The Rails app itself loads up with KCODE = true by default as well, meaning that it silently starts with Unicode support already, which is great. But that ‘encoding’ configuration has a new usage as well: everytime Rails connects to the database it will tell it to use this ‘encoding’ setting. Like issuing a ‘SET NAMES UTF8’.
One trick that we can do to DRY up our database.yml is this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
defaults: &defaults
adapter: mysql
encoding: utf8
username: root
password: root
socket: /opt/local/var/run/mysql5/mysqld.sock
development:
database: blog_development
<<: *defaults
test:
database: blog_test
<<: *defaults
production:
database: blog_production
<<: *defaults
|
Much better. We have new Rake tasks as well. And some of them are related to the database:
| db:charset | Retrieves the charset for the current environment’s database |
| db:collation | Retrieves the collation for the current environment’s database |
| db:create | Create the database defined in config/database.yml for the current RAILS_ENV |
| db:create:all | Create all the local databases defined in config/database.yml |
| db:drop | Drops the database for the current RAILS_ENV |
| db:drop:all | Drops all the local databases defined in config/database.yml |
| db:reset | Drops and recreates the database from db/schema.rb for the current environment. |
| db:rollback | Rolls the schema back to the previous version. Specify the number of steps with STEP=n |
| db:version | Retrieves the current schema version number |
We have a far better database administration support. In the older Rails now we would log into our databases admin consoles and create the database manually. Now, we can do simply:
rake db:create:all
If we want to start from scratch, we can do db:drop:all. And in the middle of development we can do db:rollback to undo the latest migration file.
Sexyness
With database set and ready to go, we can create our first Resource. Remember now that Rails 2.0 is RESTful by default (for brazilians: I am writing a separated RESTful Tutorial as well).
./script/generate scaffold Post title:string body:text
The only difference here is that the ‘scaffold’ behaves like the ‘scaffold_resource’ we had before, and the old non-RESTful scaffold is gone. You also don’t have the ActionController class method ‘scaffold’ that dynamically populated your empty controller with default actions. So, everything scaffold we do is RESTful now.
It will create the usual suspects: Controller, Helper, Model, Migration, Unit Test, Functional Test.
The main difference is in the Migration file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# db/migrate/001_create_posts.rb class CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.string :title t.text :body t.timestamps end end def self.down drop_table :posts end end |
This is called Sexy Migrations, first devised by “Err the Blog” as a plugin and it found its way into the Core. The best way to understand the different is to take a look at what this migration would look like in Rails 1.2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class CreatePosts < ActiveRecord::Migration def self.up create_table :posts do |t| t.column :title, :string t.column :body, :text t.column :created_at, :datetime t.column :updated_at, :datetime end end def self.down drop_table :posts end end |
It gets rid of the ‘t.column’ repetition and now uses the format ‘t.[column_type] [column_name]’ and the automatic datetime columns are concentrated in a single ‘t.timestamps’ statement. It doesn’t chance any behavior, just makes the code ‘sexier’.
Now, we run the migration like before:
rake db:migrate
In the old days, if I wanted to rollback a migration change I had to do:
rake db:migrate VERSION=xxx
Where ‘xxx’ is the version where we wanted to go back to. Now we can simply issue:
rake db:rollback
Much nicer and more elegant, that’s for sure. All set, we can now start our server as before and take a look at the generated pages:
./script/server

It will load either Mongrel, Webrick or Lightpd at port 3000. We have the same root page as before, showing up the index.html page. One tidbit that I didn’t show at the screencast is this:
1 2 3 4 5 6 |
# config/routes.rb ActionController::Routing::Routes.draw do |map| map.root :controller => 'posts' map.resources :posts end |
There is a new ‘map.root’ statement which have the same effect as "map.connect ‘’, :controller => ’posts’. Just a small nicety that doesn’t do anything big but tries to make the routes file feel more polished. Once you set that, don’t forget to delete the public/index.html file. Not the root URL will always be pointed to the Posts controller.

As you can see, everything feels the same as before. All the scaffold templates are the same. You can browse around, create new rows and so on.
Nested Routes
So, let’s create a companion Comment resource for the Post. That should complete our Blog’s resources:
1 2 3 |
./script/generate scaffold Comment post:references body:text rake db:migrate |
Same thing here: scaffold the resource, configure the column names and datatypes in the command line and the migration file will be already set. Notice another small addition: the keyword ‘references’. As my friend Arthur reminded me, this makes migrations even sexier. To compare, this is the old way of doing the same thing:
1 2 |
./script/generate scaffold Comment post_id:integer body:text |
Foreign keys are just implementation details that don’t matter. Take a look at the new migration file for this:
1 2 3 4 5 6 7 8 9 |
def self.up create_table :comments do |t| t.references :post t.text :body t.timestamps end end |
Take a look here for details on this new ‘references’ keyword. So, running db:migrate creates the table in the database. Then, we configure the ActiveRecord models so they relate to each other like this:
1 2 3 4 5 6 7 8 9 10 |
# app/models/post.rb class Post < ActiveRecord::Base has_many :comments end # app/models/comment.rb class Comment < ActiveRecord::Base belongs_to :post end |
Ok, nothing new here, we already know how to work with ActiveRecord associations. But we are also working with RESTful resources. In the new Rails way, we would like to have URLs like these:
http://localhost:3000/posts/1/comments
http://localhost:3000/posts/1/comments/new
http://localhost:3000/posts/1/comments/3
Meaning: ‘grab the comments from this particular post’ The scaffold generator only made it ready to do URLs like these:
http://localhost:3000/posts/1
http://localhost:3000/comments/new
http://localhost:3000/comments/3
That’s because in the config/routes.rb we have:
1 2 3 4 5 6 7 8 |
# config/routes.rb ActionController::Routing::Routes.draw do |map| map.resources :comments map.root :controller => 'posts' map.resources :posts end |
Let’s tweak it a bit. Just like in the models, we can create what’s called a Nested Route:
1 2 3 4 5 6 |
# config/routes.rb ActionController::Routing::Routes.draw do |map| map.root :controller => 'posts' map.resources :posts, :has_many => :comments end |
Just like that! Now we can do the nested URLs as showed above. The first thing to understand is that when I type in this URL:
http://localhost:3000/posts/1/comments
Rails will parse it like this:
- Load the CommentsController
- Set params[:post_id] = 1
- In this case, call the ‘index’ action
We have to make the CommentsController prepared to be nested. So that’s what we are going to change:
1 2 3 4 5 6 7 8 |
class CommentsController < ApplicationController before_filter :load_post ... def load_post @post = Post.find(params[:post_id]) end end |
This makes the @post already set for all the actions within the Comments controller. Now we have to make these changes:
| Before | After |
| Comment.find | @post.comments.find |
| Comment.new | @post.comments.build |
| redirect_to(@comment) | redirect_to([@post, @comment]) |
| redirect_to(comments_url) | redirect_to(post_comments_url(@post)) |
That should make the Comments controller ready. Now let’s change the 4 views at app/views/comments. If you open up either new.html.erb or edit.html.erb you will notice the following new feature:
1 2 3 4 5 |
# new edit.html.erb and new.html.erb form_for(@comment) do |f| ... end |
That’s the new way of doing this old statement in Rails 1.2:
1 2 3 4 5 |
# old new.rhtml form_for(:comment, :url => comments_url) do |f| ... end |
1 2 3 4 5 6 |
# old edit.rhtml form_for(:comment, :url => comment_url(@comment), :html => { :method => :put }) do |f| ... end |
Notice how the same form_for statement suits both ‘new’ and ‘edit’ situations. That’s because Rails can infer what to do based on the Class name of the @comment model instance. But now, for the Nested Route, comments is dependent on the Post, so that’s what we have to do:
1 2 3 4 5 |
# new edit.html.erb and new.html.erb form_for([@post, @comment]) do |f| ... end |
Rails will try to be smart enough to understand that this array represents a Nested Route, will check routes.rb and figure out and this is the post_comment_url(@post, @comment) named route.
Let’s explain named routes first. When we set a Resource Route in the routes.rb. We gain these named routes:
| route | HTTP verb | Controller Action |
| comments | GET | index |
| comments | POST | create |
| comment(:id) | GET | show |
| comment(:id) | PUT | update |
| comment(:id) | DELETE | destroy |
| new_comment | GET | new |
| edit_comment(:id) | GET | edit |
“7 Actions to Rule them all …” :-)
You can suffix them with both ‘path’ or ‘url’. The difference being:
| comments_url | http://localhost:3000/comments |
| comments_path | /comments |
Finally, you can prefix them with ‘formatted’, giving you:
| formatted_comments_url(:atom) | http://localhost:3000/comments.atom |
| formatted_comment_path(@comment, :atom) | /comments/1.atom |
Now, as Comments is nested within Post, we are obligated to add the prefix ‘post’. In Rails 1.2 this prefix was optional, it was able to tell the difference by the number or parameters passed to the named route helper, but this could lead to many ambiguities so it is now mandatory to have the prefix, like this:
| route | HTTP verb | URL |
| post_comments(@post) | GET | /posts/:post_id/comments |
| post_comments(@post) | POST | /posts/:post_id/comments |
| post_comment(@post, :id) | GET | /posts/:post_id/comments/:id |
| post_comment(@post, :id) | PUT | /posts/:post_id/comments/:id |
| post_comment(@post, :id) | DELETE | /posts/:post_id/comments/:id |
| new_post_comment(@post) | GET | /posts/:post_id/comments/new |
| edit_post_comment(@post, :id) | GET | /posts/:post_id/comments/edit |
So, to summarize, we have to make the Comments views to behave like they are nested within a Post. So we have to change the named routes within from the default scaffold generated code to the nested form:
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- app/views/comments/_comment.html.erb --> <% form_for([@post, @comment]) do |f| %> <p> <b>Body</b><br /> <%= f.text_area :body %> </p> <p> <%= f.submit button_name %> </p> <% end %> |
1 2 3 4 5 6 7 8 9 10 11 |
<!-- app/views/comments/edit.html.erb --> <h1>Editing comment</h1> <%= error_messages_for :comment %> <%= render :partial => @comment, :locals => { :button_name => "Update"} %> <%= link_to 'Show', [@post, @comment] %> | <%= link_to 'Back', post_comments_path(@post) %> |
1 2 3 4 5 6 7 8 9 10 |
<!-- app/views/comments/new.html.erb --> <h1>New comment</h1> <%= error_messages_for :comment %> <%= render :partial => @comment, :locals => { :button_name => "Create"} %> <%= link_to 'Back', post_comments_path(@post) %> |
1 2 3 4 5 6 7 8 9 10 |
<!-- app/views/comments/show.html.erb --> <p> <b>Body:</b> <%=h @comment.body %> </p> <%= link_to 'Edit', [:edit, @post, @comment] %> | <%= link_to 'Back', post_comments_path(@post) %> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
<!-- app/views/comments/index.html.erb --> <h1>Listing comments</h1> <table> <tr> <th>Post</th> <th>Body</th> </tr> <% for comment in @comments %> <tr> <td><%=h comment.post_id %></td> <td><%=h comment.body %></td> <td><%= link_to 'Show', [@post, comment] %></td> <td><%= link_to 'Edit', [:edit, @post, comment] %></td> <td><%= link_to 'Destroy', [@post, comment], :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to 'New comment', new_post_comment_path(@post) %> |
Some remarks:
- Notice that I created a partial to DRY up the new and edit forms. But pay attention that instead of :partial => ‘comment’, I did :partial => @comment. Then again it can infer the name of partial from the class name. If we passed a collection it would do the equivalent of the old ‘:partial, :collection’ statement.
- I can use both post_comment_path(
post, @comment), or simply [post, @comment]
- Pay close attention to not forget any named route behind.
Finally, it would be good to link the comments list to the post view. So let’s do it:
1 2 3 4 5 |
<!-- app/views/posts/show.html.erb --> <%= link_to 'Comments', post_comments_path(@post) %> <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %> |
So, I just added a link there. Let’s see how it looks like:



Completing the Views
Ok, looks good, but that’s not how a Blog should behave! The Post’s show view should already have the Comments listing and New Comment Form as well! So let’s make some small adaptations. There’s nothing new here, just traditional Rails. Let’s start at the view:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<!-- app/views/posts/show.html.erb --> <p> <b>Title:</b> <%=h @post.title %> </p> <p> <b>Body:</b> <%=h @post.body %> </p> <!-- #1 --> <% unless @post.comments.empty? %> <h3>Comments</h3> <% @post.comments.each do |comment| %> <p><%= h comment.body %></p> <% end %> <% end %> <!-- #2 --> <h3>New Comment</h3> <%= render :partial => @comment = Comment.new, :locals => { :button_name => 'Create'}%> <%= link_to 'Comments', post_comments_path(@post) %> <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %> |
More remarks
- There is nothing new in the iterator, just listing all comments
- Again, we pass in the @comment variable to the partial statement
One final adjustment: whenever we create a new post, we would like to return to the same Posts’ show view, so we change the CommentsController to behave like this:
1 2 3 4 5 6 |
# app/controllers/comments_controller.rb # old redirect: redirect_to([@post, @comment]) # new redirect: redirect_to(@post) |
Namespaced Routes
Ok, now we have a bare bone mini-blog that kind of mimics the classic blog from the ‘15 minute’ screencast David did in 2005. Now let’s go one step further: Posts should not be publicly available to anyone to edit, we need an Administration section in our website. Let’s create a new controller for that:
./script/generate controller Admin::Posts
Rails 2.0 now supports namespaces. This will create a sub-directory called app/controllers/admin.
What we want to do is:
- Create a new routes
- Copy all actions from the old Posts controller to the new Admin::Posts
- Copy the old posts views to app/views/admin* Leave the old Posts controller with only the ‘index’ and ‘show’ actions, this means deleting the new and edit views as well
- Adapt the actions and views we just copied so it understands it is within the admin controller
First things first, let’s edit config/routes.rb again:
1 2 3 4 |
map.namespace :admin do |admin| admin.resources :posts end |
In practice this means that we now have names routes for Posts with the prefix ‘admin’. This will disambiguate the old posts routes from the newest admin posts routes, like this:
| posts_path | /posts |
| post_path(@post) | /posts/:post_id |
| admin_posts_path | /admin/posts |
| admin_post_path(@post) | /admin/posts/:post_id |
Now let’s copy the actions from the old Post controller and adapt the routes to fit the new namespace:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# app/controllers/admin/posts_controller.rb ... def create # old: format.html { redirect_to(@post) } # new: format.html { redirect_to([:admin, @post]) } end def update # old: format.html { redirect_to(@post) } # new: format.html { redirect_to([:admin, @post]) } end def destroy # old: format.html { redirect_to(posts_url) } # new: format.html { redirect_to(admin_posts_url) } end ... |
Don’t forget to delete all the methods from the app/controllers/posts_controller.rb, leaving just the ‘index’ and ‘show’ methods.
Now, let’s copy the views (assuming your shell is already in the project’s root folder):
cp app/views/posts/*.erb app/views/admin/posts
rm app/views/posts/new.html.erb
rm app/views/posts/edit.html.erb
Now, let’s edit the views from app/views/admin/posts:
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- app/views/admin/posts/edit.html.erb --> <h1>Editing post</h1> <%= error_messages_for :post %> <% form_for([:admin, @post]) do |f| %> ... <% end %> <%= link_to 'Show', [:admin, @post] %> | <%= link_to 'Back', admin_posts_path %> |
1 2 3 4 5 6 7 8 9 10 11 |
<!-- app/views/admin/posts/new.html.erb --> <h1>New post</h1> <%= error_messages_for :post %> <% form_for([:admin, @post]) do |f| %> ... <% end %> <%= link_to 'Back', admin_posts_path %> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<!-- app/views/admin/posts/show.html.erb --> <p> <b>Title:</b> <%=h @post.title %> </p> <p> <b>Body:</b> <%=h @post.body %> </p> <%= link_to 'Edit', edit_admin_post_path(@post) %> | <%= link_to 'Back', admin_posts_path %> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!-- app/views/admin/posts/index.html.erb --> ... <% for post in @posts %> <tr> <td><%=h post.title %></td> <td><%=h post.body %></td> <td><%= link_to 'Show', [:admin, post] %></td> <td><%= link_to 'Edit', edit_admin_post_path(post) %></td> <td><%= link_to 'Destroy', [:admin, post], :confirm => 'Are you sure?', :method => :delete %></td> </tr> <% end %> </table> <br /> <%= link_to 'New post', new_admin_post_path %> |
Almost done: if you test http://localhost:3000/admin/posts it should work properly now. But, it will look ugly, and that’s because we don’t have a global app layout. When we did the first scaffolds, Rails generated specific layouts for Post and Comment alone. So let’s delete them and create one that’s generic:
cp app/views/layouts/posts.html.erb \
app/views/layouts/application.html.erb
rm app/views/layouts/posts.html.erb
rm app/views/layouts/comments.html.erb
Then let’s just change the title of it:
1 2 3 4 5 |
<!-- app/views/layouts/application.html.erb --> ... <title>My Great Blog</title> ... |
It only remain the old ‘index’ and ‘show’ pages from the previous Posts controllers. They still have links to the methods we deleted, so let’s rip them off from those links:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<!-- app/views/posts/index.html.erb --> <h1>My Great Blog</h1> <table> <tr> <th>Title</th> <th>Body</th> </tr> <% for post in @posts %> <tr> <td><%=h post.title %></td> <td><%=h post.body %></td> <td><%= link_to 'Show', post %></td> </tr> <% end %> </table> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<!-- app/views/posts/show.html.erb --> <p> <b>Title:</b> <%=h @post.title %> </p> <p> <b>Body:</b> <%=h @post.body %> </p> <% unless @post.comments.empty? %> <h3>Comments</h3> <% @post.comments.each do |comment| %> <p><%= h comment.body %></p> <% end %> <% end %> <h3>New Comment</h3> <%= render :partial => @comment = Comment.new, :locals => { :button_name => 'Create'}%> <%= link_to 'Back', posts_path %> |
We can test everything from the browser, go in http://localhost:3000/admin/posts and see that everything is working properly now. But, we still have one thing missing: an administration section should not be publicly available. Right now you can just jump in and edit everything. We need authentication.
HTTP Basic Authentication
There are several ways of implementing authentication and authorization. One plugin that’s widely used for this is restful_authentication.
But, we don’t want to make anything fancy here. And for that Rails 2.0 gives us a great way of authenticating. The idea is: let’s use what HTTP already gives us: HTTP Basic Authentication. The drawback being: you will definitely want to use SSL when going into production. But, of course, you would do it anyway. HTML Form authentication is not protected without SSL either.
So, let’s edit our Admin::Posts controller to add authentication:
1 2 3 4 5 6 7 8 9 10 11 12 |
# app/controllers/admin/posts.rb class Admin::PostsController < ApplicationController before_filter :authenticate ... def authenticate authenticate_or_request_with_http_basic do |name, pass| #User.authenticate(name, pass) name == 'akita' && pass == 'akita' end end end |
You already know what ‘before_filter’ does: it runs the configured method before any action in the controller. If you set it in the ApplicationController class, then it runs before any action from any other controller. But we only want to protect Admin::Posts here.
Then, we implement this method and the secret sauce is the ‘authenticate_or_request_with_http_basic’ method that let’s us configure a block. It gives us the username and password that the user typed in the browser. We would usually have a User model of some kind to authenticate this data, but for our very very simple example I am hard coding the checking, but you get the idea.







Nice tutorial, Akita! :)
In Rails 2.0 you can use:
./script/generate scaffold Comment post:references body:text
I think it’s even more more sexy!
In Rails 1.2 you’d write:
create_table :taggings do |t|
t.integer :tag_id, :tagger_id, :taggable_id
t.string :tagger_type
t.string :taggable_type, :default => ‘Photo’
end
Now, in Rails 2.0 you can write:
create_table :taggings do |t|
t.references :tag
t.references :tagger, :polymorphic => true
t.references :taggable, :polymorphic => { :default => ‘Photo’ }
end
And t.belongs_to is an alias for t.references
More about that in: http://dev.rubyonrails.org/changeset/7973
Amazing Akita, always writing good materials ;-)
Cheers,
Akita. O que é prioritário atualmente pra você? Lutar pela disseminação do Rails para Brasileiros?
Thanks so much for the video and these great tutorials. I just started a new project last night and your tutorials have helped me solve some problems, and do things better.
Keep up the great work!
Eraldo, minha prioridade é: trabalhar com o que gosto e me divertir no caminho. Tudo que vier junto com isso é lucro ;-)
Arthur, hey, great tip. I updated the post to add this information.
BTW, I also updated Part 2 because I forgot to mention Cookie Session Store.
Rapaz,
Formatado assim tinha ficado mais fácil de eu gerar o PDF.
Vou gerar novamente depois usando as formatações do teu blog. Acho que fica mais bacana. Mandei pra ti no teu e-mail agora pouco.
Abraço!
Fabio,
Thanks for helping get us up to speed with the great tutorials. We look forward to even more.
Rob
When I try to go here
http://localhost:3000/posts/1/comments
I get
undefined method `comments’ for #
What am I doing wrong?
Sorry, I’m a noob to rails
Great article! Just a note for those using has_one associations:
Say you have ‘idea’ and ‘idea_response’ resources and each Idea will have at most one IdeaResponse. Instead of using ’@idea_response = @idea.build(params[:idea_response])’, you need to use ’@idea_response = @idea.build_idea_response(params[:idea_response])’. Notice that the function call to ‘build’ needs to be dynamically named to the nested resource (‘build’ becomes ‘build_idea_response’). I spent the whole day figuring this one out, and I hope it helps someone out there.
A minor typo:
redirect_to(@comment) should be changed to read: redirect_to(@post, @comment) not redirect_to(post, @comment)
btw how do you get your ruby code nicely formatted for insertion into a blog?
Thank you for the tutorial. Please post more.
Hi,
Thanks for the nice and very useful tutorial. I am new to rails and couldn’t follow everything at once. If possible, can you please share the code.
thanks, Kris
Thanks for the great writeup! Rails 2.0 is looking pretty spiffy. Now if only I had the time to fully update my old 1.2 app. . .
-dath
Fábio, muito bom material, mas eu peço por favor, quando fizer a versão em português, use outro exemplo que não seja um blog, pois o Rails tá com cara de blog designer e esses termos “tag” “tagger” “taggable” parecem tudo a mesma coisa.. :)
One extra gotcha I found was if you are running rails 2.0.2 it will default on a Mac to SqlLite3, to enable MySQL you need to use rails -d mysql blog rather than rails blog
One extra thing, if you change the generate for comment to references, then you need to use post_id rather than post in the comments views otherwise you get a cryptic number rather than the post id
I find that using that DRY database.yml I can’t actually generate the DB?
Thank you, for this great tutorial. It covers some neat changes and introduces REST really cool!
Thank you very much for this excellent introduction to Rails 2.0. I’m using this as a drop-in replacement for the not-yet-updated AWDWR. :-)
Could you post the full, completed html.erb files?
Please fix tutorial. Rob’s comment dated 13 Dec 17:59 has not been addressed as the same problem occurs for me.
Thanks and great post!
rob and maxrcul, sorry for the delay, but it seems that you didn’t place this line in your app/models/post.rb file:
has_many :comments
great stuff
wonderful to see a tutorial like this so soon after rails 2.0 came out.
the only slight wee bit of criticism would be the admin post controller part. I had to read it a few times to understand that you really do mean to copy ALL of the existing controller over, and then simply change the redirect links to the code you have written out. if you are in the mood to tweek, perhaps you can just cut and paste the controller in? either way, great stuff.
thank you so much akita for the time and efforts you put into the tuts!!!
Hi there. Thank you so much for such a detailed tutorial. I would never have begun with Rails 2.0 this soon without it. I have “agile web dev” but the tutorials in it are now mostly broken.
Thanks to the others who left comments and corrected some typos and issues that had me scratching my head for some time!
You’ve done rally well showing how to have an admin section and basic authentication. Is someone able to tell me how to make a logout link for the admin section?
Many thanks, keep up the good work. Gabriel.
Nice tutorial
thank you for this great tutorial on Rails 2!
Hi Akita. Greetings from South Africa. Great tutorial. Your screencast was quite fast so I had to view it several times just to keep up. I have used your example to create my own project but I need to take it a step further. To use your post/comments example I would like to add an additional layer for example add a response to a specific comment(has_many => responses) so that you are able to create a response from the post/comments/show view. How would this affect the actions/nested routes in the responses controller – does it have to make reference to the comments controller only or should it also make reference to the posts controller? How would the additional method look in the responses controller i.e. load_response, @comments = Comments.find(params[:comments_id]) or should it be looking for the posts as well? Thanks in anticipation
Your tutorial helps alot. I’m just starting Rails and almost every books in town uses rails 1.2. Its kinda difficult for me to test and develop an application using newer rails (2.0.2) when the available references uses 1.2. Thanks again Akita.
awesome!!
I’ve been googling for 2 days for nested routing at Rails2.0.
So far your article is the best I’ve ever seen about Rails2.0. THANKS!
OMG! I am still learning Rails myself, but this was the most fun I have learning anything. I did get those few hiccups when I did, but it felt good for me to figure out those for myself. Thanks for the great intro!
thanx for writing a nice tutorial on rails 2.0. willing to see more on this and also on Rspec.
thank you for this was a fantastic demo! i’ve begun writing a blog based on your code and it’s coming along.
one thing that’s really lacking in rails tutorials everywhere is persistence. i’d love to see you take this little blog application and run with it – with the ultimate goal of developing blog software that features user submitted comments, comment moderation, captcha, user authentication with rest, tags, and possibly cookied themes.
that would just about make my year, and here it is just starting! :)
cheers and thanks
First of all – thanks for this excellent tutorial. That would be a great start for a whole book I’d immediately purchase! Just one thing: it would be great to have a “print view”. Unfortunatly one can’t print your tutorial fine at the moment – neither with Firefox, nor with Internet Explorer.
Hi,
Thanks for the great tutorial. Just got started on a new RESTful project and this one really helped out. Im trying to make my comments controller inside a subdirectory “module/comment_controller.rb”
In this case how can I modify routes.rb so that i can get /user/:id/comments as normal?
I cant seem to find any detailed tutorials on building apps with sub controllers.. maybe that can be your next one :)
thankx! good job!
ótimo trabalho fábio, foi vc que fez o video tutorial do www.rubyonrails.com sobre blog, muito om os dois um complemta o outro. parabens
Um abraço.
redirect_to(post, @comment) There is one error. undefined `post’.
post must change to @post.
Como fazer com algo do tipo: script/generate scaffold Model ‘admin/model’?
Obrigado
Very good! Beginners need it _.
I am getting a Segmentation Fault from Ruby when I attempt the “rake db:create:all” command.
Using rake 0.8.1, ActiveSupport 2.0.2, Ruby 1.8.6p111 on Windows Vista. Also mysql 5.1.22-rc.
Not really sure where to do from here. Anyone else having this issue?
Great tutorial, thanks!
Why is it that the Rails community makes such a big deal about test driven development and yet every single tutorial (book or web) completely ignores testing or at best deals with it is an after-thought?
Great tutorial! I also was searching for a tutorial that covers 2.0. I’m just starting to learn Ruby and Rails and all tutorials and books are not up-to-date yet.
Great tutorial!
Great Tutorial, one quick correction however, near the start where you go through changing the CommentsController, the following says Before After redirect_to(@comment) redirect_to(post, @comment)
It doesn’t work for me unless i do
Before After redirect_to(@comment) redirect_to(@post, @comment)
o tutorial e bom d+. vc conhece si ja tem algum ebook pra rails 2.x?. saudades desde argent.
Thanks for putting this together. Unfortunately, I’m a complete newcomer to ruby and rails. I followed the steps but they didn’t actually work for me. This appears to be great for someone who is already familiar with rails. The other 2 tutorials appear to be based on a pre 2.0 rails, and I have yet to actually get anything to come up other than the welcome page (I keep getting Unknown action or no method#index errors).
Bah Akita, mais uma vez dando um show de conhecimento e humanidade, compartilhando um pouco do seu conhecimento com a comunidade… Parabéns e obrigado pelo ótimo trabalho… E a segunda edição do livro??? Valew!
thanks a lot for this great tutorial and many greetins from germany, düsseldorf !
I was just too frustrating for a complete novice to use the Agile book with 2.0. My plan is to learn 1.2 and then come back here when the terminology makes sense. Thanks for the work!
b
Any chance of changing the layout of your page? I ask because the content of the blog occupies only about 1/3 of the screen, and that means that readers are forced to scroll in all of your examples. As a result, it is difficult to benefit from your well-expressed ideas.
Hey Dan, there’s always room for improvement. If you know any good and unobtrusive Mephisto theme, please let me know.
Fabio, I love the stuff you’ve been putting out. You turned me on to resource_controller this weekend, which prompted me to write an article which will appear on infoq this week. A second for formatting options on this page. I’d love to print this article, but it really looks ugly on print, all the good stuff is squeezed to the left. Any chance of a print style sheet? I know “beggars can’t be choosers.”
Hi Rick, I know you :-) I am most flattered by having you reading my stuff. I am glad you liked and you’re right: my blog is lacking a print version. You’re not the first to ask me this and I have to confess that it is stalled in my todo list. I’ve been very overwhelmed lately but I am surely making a print version as soon as possible, specially after yet another request. Thanks.
hi Akita, for a lightweight mephisto theme, try micro.
This needs to be the first tutorial listed on the rails documentation page.
At the tutorial point:
the redirect_to(@post, @comment) call already redirect to the post page!!!! the effect is the same of redirect_to(@post) ... how is this possible?
Hey, I solved the mistery myself!!
errata: CHANGE redirect_to(@post, @comment) TO redirect_to([@post, @comment])
because redirect_to(@post, @comment) acts as redirect_to(@post)
bye!
@nobrin, thanks you’re right, I just fixed this typo.
Everything in the Tutorial work by me.
Now I want to make some additional actions (like ‘download’). And I define them in the controller.
I want to use the new action. So I add this line to my view(index.html.erb): ”<%= link_to ‘Download’, [:download, @project, document] %>
But when I call the view I receive the Error: “NoMethodError in Documents#index”
When I call the action directly via url I receive following error: ” ActiveRecord::RecordNotFound in DocumentsController#show” “Couldn’t find Document with ID=download AND (documents.project_id = 1)”
The routes.rb looks like: ” map.namespace :admin do |admin| admin.resources :people end
map.resources :documents
map.root :controller => ‘projects’ map.resources :projects, :has_many => :documents”
I hope you can help me.
Thanks.
The big fat “map.resources :documents” is comment in my routes.rb.
@robin: I think you misunderstood it. What you want is:
Right?
This means named URLs as:
Or route shortcuts as:
If you do:
It means that you want to call the custom action names ‘download’ in the projects controller, something as:
and
Get it?
Thanks for your quick answer.
hey, thanks for the great tutorial…
Great tutorial! I’ve gone through it and it’s helped me immensely. But I am having one problem I can’t get past.
It seems the child records in the has_many/belongs_to do not get the parent’s id in their foreign key fields. So, using the example from the tutorial, the Comment records do not refer back to any Post. If I modify the database directly, everything else works fine. It seems it is just the initial creation of the child record that is the problem.
Any advice would be greatly appreciated as I’ve searched quite a lot and seem to be stuck at this problem. Thank you!
Hi Fabio, Thanx for this great tut! This was my liftoff in Rails development (finally). I’m coming from PHP and I’m glad to erase that language from my life :-)
Rails rocks, and you too!
Thankyou for excellent tutorial. I wonder if you did anything with the tests when doing this. In particular I’m having difficult moving the functional test to the admin section. Any chance of a tutorial update to deal with that?
I wanted to answer my own question from above, in case it may be any help to others.
I had missed the step in the controller changing from
Comment.new
to
@post.comments.build
I was using the PDF version of the tutorial, and this step wasn’t as obvious.
If i wanted to have a link to a url like this:
localhost:3000/documents/?update=true
how would i format my link_to?
i tried <%= link_to ‘Refresh List’, documents_path, :update => ‘true’ %>
but it didnt work
I got it to work with
<%= link_to ‘Refresh List’, {:action => ‘index’, :update => ‘True’} %>
but i wanted to do it using the named routes… is that possible
Sorry for question from newbie. If it is not one thing, its another. Good Ruby 2.0 tutorial – as far as I got! Like style better than other books/tutorials so I am sticking with this one. Problem: When running rake db:migrate, got SQL error: “Access denied for user ‘root’@’localhost’ (using password: YES)” I installed InstantRails (WindowsXP), and think it may be using sqllite. How do I tell? How do I fix or change? —Thanks
Sorry about the last post – I didn’t realize the example put in a password. Changed it to my password, then got following error: “Unknown database ‘blog_development’ ” I though we set this up in the ‘database.yml’ file. ???
Back again. Found the problem. Needed to run ‘mysql’ and create the database from the shell (using ‘create database blog_development;’ etc.) Not mentioned above. Don’t know if it’s necessary, but I include ‘grant all on blog_development.* to ‘ODBC’@’localhost’;
Hi all, very good tutorial. Sorry if it’s a silly question, but I’m new in RoR, so I have a question. In the post view with the comments, is it possible to show error messages from the comment model ?
Darwiin,
I’m a bit of a Rails newbie myself but I believe you just need to include:
<%= error_messages_for :comment %>
Somewhere in your views/posts/show.html.erb
@Pete
Thanks for your answer. I’ve already tried this but it doesn’t seems to work.
Hmm, I’ve just tried it and the best I’ve managed so far is to include ‘error_messages_for’ in the file that defines the comment form partial. This will show you any errors, but not inline on the post page, you get redirected to comments/new.
I have a feeling this can be overcome by altering the format.html { render :action => ‘new’ } line in the comments controller’s create method, but I’m not sure how!
Hello,
I used the dynamic scaffolding to set up the application. Afterwards I changed to static. Is there a possibility to redo the “generate scaffold” after modifying the database e.g. inserting columns?
Thanks a lot!
yeah, is there something else in the routes.rb or something where we have to add something to make the partial work so that the edit.html.erb and new.html.erb link to the _comment.html.erb that we created?
Okay, I figured it out, I had some simple syntax problems.
<%= f.submit :button_name %>
instead of
<%= f.submit button_name %>
and <% render instead of <%= render
Okay, I’ve made it as far as the admin, copied the views into views/admin/posts. The new.html.erb and edit.html.erb do not work for me. It hangs up on this line (line #5):
<% form_for([:admin, @post]) do |f| %>
and I get this error:
RuntimeError in Admin/posts#new
Showing admin/posts/new.html.erb where line #5 raised:
Called id for nil, which would mistakenly be 4—if you really wanted the id of nil, use object_id
what’s going on here??? I have double checked, triple checked, quadruple checked, etc, etc, etc and my code matches perfectly with the tutorial.
That’s really strange. I just checked in my installation and it works fine. Can you double check with my source code ?
Yeah, I was missing the ‘new’ and ‘edit’ actions in my controller from when I moved it under admin.
Just got through the tutorial. Great work. Only had to start over once! I can see that this is really powerful stuff.
great tutorial but when i try to open: http://localhost:3000/posts/1/comments
I get this: Couldn’t find Comment without an ID
Request Parameters shows: {“post_id”=>”1”}
I posted a little tut, How to Do has_one Nesting in Rails 2.0 showing one way to handle nested routes with has_one associations.
Great tutorial, Fabio, you’re a life saver.
Ron
Gracias por el Tutorial Akita, muy bien explicado. Tu trabajo es de gran utilidad.
Thanks for your nice post, it help me a lot about rail2, any way how can i set id to the from_for, i have searched a lot of place but i failed, can u help me?
<% form_for([:admin, @post]) do |f| %> ... <% end %>
How would I use a path prefix to my restful routes?
ex.
Instead of “http://mysite.com/articles/1… Have “http://mysite.com/blog/articles/1…
Do i make a separate controller? script/generate controller Blog::Articles ?
Or is it something simple that I’m completely overlooking?
Great Tutorials!
This tutorial is that thing which I was looking for. I must admit that rails 2.x changed many basic things, names conventions, so I think that your tut is the first that drives as through this version. Thanks a lot. Much more tuts like this.
regards kotosha
NameError in Comments#index
I get this error when trying to access “http://localhost:3000/posts/1/comments” i have checked the post/comment.rb and they seem to be set up correctly.
@jYeCkeL : It seems you have some syntax error. Try to check it out again.
@AkitaOnRails:
I have one question. Suppose I’d like to divide my posts into categories. I know that I have to generate another controller Categories but how to connect this f.e. with changes in routes.rb, relations with files. I would be grateful for any ideas, hints, suggestions.
@anybody who can help
What if I want to view all comments for all posts on a single page? Obviously you wouldn’t want to do this in the blog example, but for my own purposes I need to display all child nodes on a page.
Thanks!
@RyanTuosto
I think you would do something like
Post.find(:all).each do |post| post.comments.each do |comment|Oops… bad formatting.
Post.find(:all).each do |post|
post.comments.each do |comment|
//print the comment… <%= comment.body %>
end
end
Actually if you just want all comments just go directly: Comment.find(:all)
Is there a reason to not doing the DRY in the new and edit form of the post. (with the render :partial)
I was trying to do that in the admin interface and it gives me an error saying that posts/_post does not exists, which is true because the one that exists is admin/posts/_post, is there a way to tell the render :partial @posts to use the namespace? I have tried with <%= render :partial => @post … %> and with: <%= render :partial => [:admin, @post]... %> both dont work
Hey, the way to fix the problem I found in the admin interface with render :partial is to put the string “post” instead of the variable @post.
So in my final new.html.erb and edit.html.erb , both have the <%= render :partial => “post”, :local => {...} %>
woohoo!!!
thanks for the great tutorial… found it really helpful.
First, Thanks for this tutorial. Nevertheless, I’m a novice in RoR and I don’t understand where this error occurs.
undefined method `comment_url’ for #
Thank you very much for this tutorial!!! I didn’t used rails for quite a while, and when i tryied the same steps as in pre 2.0 i recieved error after error. With your tutorial i finally get everything to work as it used to.
Great work!! thanks very much. Just one suggestion : it could be nice to provide one source archive with rails freezed. ;)
@Niko:
It occurs in one of your views. Search for “post_comment_url(@post, @comment)” in this tutorial. You probably missed changing something that he changed in the tutorial.
@AkitaOnRails:
Consider we want to categorize our posts.. I wonder how routes.rb should be written for our categories_controller.rb
A very nice and useful article on Rails 2.0. A must for people starting out on Rail 2.0
Hi Akita…
I followed your tutorial… It is really what I was looking for.
I’ve been looking for a admin tutorial like this for a long time.
Almost everything is working on my side except that when I try to save or edit a post it displays the following error
undefined method `symbol_url’ for #
/var/lib/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/polymorphic_routes.rb:27:in `send!’ /var/lib/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/polymorphic_routes.rb:27:in `polymorphic_url’ /var/lib/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:618:in `url_for’ /var/lib/gems/1.8/gems/actionpack-2.0.2/lib/action_controller/base.rb:1060:in `redirect_to’ app/admin/acupunctures_controller.rb:52:in `create’...
I’ll post the entire stack if necessary
Abracos
I figure it out…
I forgot the square brackets here format.html { redirect_to([:admin, @post]) }
Hi Akita,
Thank you for a wonderful tutorial. I followed it and everything works like a charm! HOWEVER, one wierd issue and I could not search anywhere on the web.
Issue: I used the Admin namespace. I am also using a template in application.html.erb which has an image in the header. For pages in the Admin namespace, I can see the header image only on the index page and not on any other!! Stylesheet works, partial forms work but the only thing missing is the image. When I look at the server it tells me layout.erb (not_found). Please help!
Great demo! I added a link to posts index view <%= link_to ‘Administer’, admin_posts_path %> to give me an easy way to get to admin and it takes me there without any authentication. I thought I would have to authenticate prior to opening the admin/posts page. How do I force authentication?
Hello to everyone, AkitaOnRails CONGRATS!! this is really good!!! I’m new and i’m really enjoying this!
I can not get to work the app though.
when i try to view the comments related to a post it says ” NoMethodError in CommentsController#index”
Anyone can helpme out with this?
Thank you all before hand
Awesome tutorial. really informative. also the screencast. so fully packed with compressed information that you have to play, stop, rewind :) I really like it alot.
Although i have one question:
You use map.resources :posts, :has_many => :comments in your routes.rb. Why are we able to use :has_many here? The api tells me resources has no option called :has_many. am i missing sth obvious here?
Nonetheless, how do i specify routes with multiple has_many connections?
Thanks alot in advance
morbyte
thankx a lot, thi one great.
This is a really great tutorial. Thanks!
The only question I have is how do I get the error messages for a comment to display on the post’s screen and not on the generic comment screen, since afterall, a comment is nested inside a post. Much thanks for any help!
Akita,
Thanks for the excellent tutorial, this is my reference point when I have something quick to cook up :)
Wrt to the comment by “Robin em” on “01 Feb 09:43”, I think his specific question was:
How do i get a url like [projects/:project_id/document/id/download] where you have the documents as a nested resource under projects resources but you need a download action for the document resource?
So in routes.rb it will be: map.resources :projects do |project| project.resources :documents, :member => [:download] end
Is there a easier one-line way to write the above using has_many instead of the block?
and the download action will be a method in documents controller and not the projects controller.
The line: rake db:create:all should be: cd blog rake db:create:all
- app/views/posts/show.html.erb -> <%= link_to ‘Comments’, post_comments_path(@post) %> <%= link_to ‘Edit’, edit_post_path(@post) %> | <%= link_to ‘Back’, posts_path %> but I got a NoMethodError in Posts#show so I downloaded your source code and it says:Title: <%=h @post.title %>
Body: <%=h @post.body %>
<% unless @post.comments.empty? %>
Comments
<% @post.comments.each do |comment| %><%= h comment.body %>
<% end %> <% end %>New Comment
<%= render :partial => @comment = Comment.new, :locals => { :button_name => ‘Create’}%>
<%= link_to ‘Back’, posts_path %>
I tried this code and I still get the NoMethodError in Posts#show
Regards, Bill
Fairy new to ror, just upgraded to rails 2.0 just to add to to my confusion. Followed this tutorial and got every thing working…thanks.
I was playing around and wanted to add an ‘edit’ link next to each comment in the post. I believe that “edit_post_comment_path” in my post view would work just don’t know how to pass in the parameters its looking for.
I get the following error: edit_post_comment_url failed to generate from {:controller=>”comments”, :action=>”edit”} – you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: [“posts”, :post_id, “comments”, :id, “edit”]
Due to my lack of experience I don’t know how to format pass in the parameters. Any ideas
Awesome Tutorial
Excellent tutorial! Wish I had read it earlier.
I’m new at rails and trying to find my way. I found your tutorial very helpful with my endeavors but the part of the Nested Routes gets pretty fuzzy after the sentence:
“So, let’s create a companion Comment resource for the Post. That should complete our Blog’s resources:”
Using a bit from the Ruby on Rails Revisited blogpost (link below) i had the following changes which makes the Nested Routes a little bit easier to accomplish.
http://www.onlamp.com/pub/a/onlamp/2007/01/05/revisiting-ruby-on-rails-revisited-2.html?page=4
I have these entries in my routes.rb
map.resources :episodes map.resources :shows, :has_many => :episodes
Now with the understanding that Rails will parse http://localhost:3000/posts/1/comments in the manner you described i can do the following to my episodes_controller.rb’s “index” class:
change ”@episode = Episode.find(:all)” to
if params[:show_id].nil? @episodes = Episode.find(:all) else @episodes = Episode.find(:all, :conditions => [“show_id = ?”, params[:show_id]]) params[:show_id] = nil end
Now i can make a link in my app/views/shows/index.html.erb to go to the episodes belonging to a particular show with
And in the app/views/shows/show.html.erb i can make the same link with <%= link_to ‘Episodes’, show_episodes_path(@show) %>
This way i don’t have to make a new class inside my episodes_controller.rb and i don’t have to alter all my Views files to adjust the named routes in the files the Scaffolding generated. It saved me a lot of time using nested routes this way.
hey found a potential bug with the latest edge rails.
if you git the latest verion, and you try to nest the namespace and controller ie
script/generate controller Admin::Posts
There will be an error that says Admin::PostsHelper is a reserverd name
I did it with Admin::Pages, but i assume it would happen on any nested controller that is created after scaffolding the model.
Anyone experience this or know a fix?
It seems like a bug with the latest edge rails. I tried to rename all the controller manually after creating them with “Admin::Post”. And, they all works fine.
I still am still trying to figure out the problem here.
Hi, thanks for the tutorial. I have a question. What is the proper way to update/alter a model that you have already used “scaffold” on. For example, lets say I want to add a new column “category” to “Posts”. According to the Agile book, I should use “script/generate migration add_category”. But my question is, how will my original scaffolding be affected? and how can I update my scaffold to reflect the new added column? Thanks.
Hi, thanks for the tutorial.
The error with rails 2.1 is: ” The name ‘Admin::PostsHelper’ is either already used in your application or reserved by Ruby on Rails. Please choose an alternative and run this generator again.”
the file PostsHelper.rb exists in the helpers sub-directory.
the definitely would like to get updated in the tutorial on what to do with this problem..
siong1987, your original scaffolding will not be affected at all. You will need to go into your view files and add the new field manually. This is very simple; you probably will just need to copy one of the existing fields in the scaffold and update it to reflect the new column that you added to the table.
sorry, that was meant for vinh, not siong1987.
@john: simple rename the existing File ‘posts_helper.rb’ to something else and it should work. I had the same problem :D
This is a very really great tutorial. Thanks!
Hi Akita, really great tutorial. map.resources :posts, :has_many => :comments, :has_many => votes ?
But I get an error when I want to link from one comment to see all votes (score and date) I tried this as a link to all votes in /comments/show.erb.html : <%= link_to ‘Votes’, post_comment_votes_path(@post, @comment) %>
undefined method `post_comment_votes_path’ for # ...
Any ideas or comments to properly apply this tuto to n levels ?
Thx for all
Olivier
Wonderful tutorial, it is too much and very helpful information on Rails.
Rails technology is becoming very popular on these days few time back, there were hosting providers whom weren’t using Rails for their clients, but today i have seen number of popular web hosts using the Rails technology.
Thank you for such a great post.
thanks for tutorial!
Hi All,
I’m starting a “kind of” translation for this tutos in French. I will try to maintain the French version up-to-date with RoR version (I mean, making modification in-place).
Thanks for the big job Pat
@esppat awesome, send me an e-mail at fabioakita@gmail.com and I can send you the original Textile files.
Pierre translated the Rails 2.1 version in french. Here: Part 1 and Part 2
Irmao,
When I write: map.root :controller => ‘posts’, then http://localhost:3000/ gives me an error. I have to write map.root :controller => “posts” instead (with double quotes).
Thanks so much for this tutorial!
— ge
Thank you very much
Thanks!
@silvio,
Regarding ./script/generate controller Admin::Posts
Renaming the helper file didn’t work with me. I just dragged the existing file to desktop and deleted the original file. I ran the script and placed the helper file back.
Hello Akita,
Thanks very much for this enlightening tutorial!!
As a relative newcomer to ROR i managed to work through it without any major difficulties.
On to part 2!
Hi Fabio. Thanks for your work.
Your directions for the namespaced controller doesn’t work (with 2.1):
$ ./script/generate controller Admin::Posts
The name ‘Admin::PostsHelper’ is either already used in your application or reserved by Ruby on Rails.
Please choose an alternative and run this generator again.
I didn’t see anything in the 2.1 addendum to this that addresses this issue. It would be helpful to lots of people if you could modify this to work with 2.1. Thanks again.
I ran into the same thing as Brandon above, any update on this? I can’t seem to find much about it. Short of running your source as my app, I can’t figure it out. I am totally new to rails though so maybe it’s simple.
@Brandon, @Coreyt and others with the same problem. If you just move away the offending file out of the helper folder and then run the generator, it will work. The problem is that it is not that common to create resources with the same name, even though one of them is nested under another namespace. Helpers are not nested, that’s why the second generation will try to overwrite a file that already exists and fails.
@Brandon, @Coreyt and others
I have just been through this problem and I solved it by running
$ ./script/generate controller admin/posts
Very nice tutorial. This has probably saved me a few hours of blood, sweat, and tears. Thanks!
Nice work. An helpfull tutorial.
I had a problem with the rake db:create:all command giving me a syntax error. (This question was asked a few times above.)
Turns out I had a tab character in the file. Once removed everything ran great.
In http://localhost:3000/posts/1 page
If I add a comment gives
undefined method `stringify_keys!’ for #
Why this error? how to resolve this
Impressed …like it …really beautifully made…and covered ….thanx a tonne…
This is by far the best Rails 2.0 blog tutorial I’ve found. All went well until I tried to create the Admin controller. “./script/generate controller Admin::Posts” The error it prints: “The name ‘Admin::PostsHelper’ is either already used in your application or reserved by Ruby on Rails.” Has anyone else gotten this error? I’ve recoded the tutorial twice, and I got the error both times. I’m using Rails 2.1.1 if that makes a difference?
Hi,
I have tried using file_columns for upploading pictures but can’t get it work. All examples I found seems to be from using an older version of Rails.
I’m using netbeans 6.1.
The files(pictures) are loaded but the field “image” is not updated with the url.
Below is a simple example taken from one of the views and the model.
Is it possible that file_columns won’t work with rails 2 or what am I dong wrong?
Update Area
<%= error_messages_for :area %>
<% form_for(@area, :html => { :multipart => true }) do |f| >
= f.text_field :name %>Name
<
Picture
<%= file_column_field “area”, “image” %>
Description
<%= f.text_area :description %>
Comment
<%= f.text_field :comment %>
<%= f.submit “Update” %>
<% end %>
<= link_to ‘Show’, @area %> |
<= link_to ‘Back’, areas_path %>
class Area < ActiveRecord::Base
validates_presence_of :name
has_many :houses
file_column :image
end
Please ignore my previous post, and thank you very much for this tutorial!
While trying to learn Ruby on Rails 2, I found tutorials about Ruby on Rails 1.2 (not what I wanted), tutorials about updating from Ruby on Rails 1.2 to 2 (not what I wanted), tutorials about Ruby on Rails 2 (what I wanted), tutorials about installing Apache, MySQL, Ruby and Rails separately (not what I wanted) and all together (what I wanted), tutorials about installing on Linux (not what I wanted), Mac OS X (not what I wanted) and Windows (what I wanted). The tutorial with what I wanted and more is at:
http://www.sitepoint.com/article/learn-ruby-on-rails
good tutorial, thanks
what is the main use of
1)map.resources
2)nested resources
3)if we use only
map.connect ‘:controller/:action/:id’
map.connect ‘:controller/:action/:id.:format’
in routes.rb ,then what is the drawback of that ?
can any one ?
Hi Vvlist.
I also encountered the same error on creating the controller “Admin::Posts”. How did you get away with it? Can anyone explain this to me?
Thanks!
Great tutorial, my app’s tend to have a bunch of parent/child objects so to have that and nested routes explained at the same time is a great help.
For anyone else having a problem with your child object not being attached to your parent (i.e. after creating a new comment in this app. and it not being attached to the parent post). Make sure you change Comment.new to @post.comments.build in two places, in def new and def create of your comments controller.
hth,
Ciaron
Hello, Nice tutorial
I have a question
what if i already have my database created ?
can i generate the model by “reverse engineering” ?
Thanks.
Great explanation of nested routes. Thanks!
Savemy day. thanx ;-)
Fantastic tutorial, really well written and explained. Only thing I had to do was delete the existing posts_helper.rb PostsHelper from app\helpers before running:
./script/generate controller Admin::Posts
Thanks!! (^ ^)
Oh, and I also added:
map.connect ‘admin’, :controller => ‘admin/posts’
…to the routes.rb file, so that going to http://localhost:3000/admin takes you to the posts index.
This tutorial is perfect for me. I think that your tut is the first that drives as through this version. Thanks you !
Congratulations!!!!!!!!!!!!!
Help me please with ruby script/server step, I have this output:
=> Booting WEBrick…
=> Rails 2.1.2 application started on http://0.0.0.0:3000
=> Ctrl-C to shutdown server; call with —help for options
[2008-11-18 17:34:02] INFO WEBrick 1.3.1
[2008-11-18 17:34:02] INFO ruby 1.8.6 (2007-09-24) [i386-mswin32]
[2008-11-18 17:34:02] WARN TCPServer Error: S¾lo se permite un uso de cada dire
cci¾n de socket (protocolo/direcci¾n de red/puerto) – bind(2)
c:/ruby/lib/ruby/1.8/webrick/utils.rb:73:in `initialize’: S¾lo se permite un uso
de cada direcci¾n de socket (protocolo/direcci¾n de red/puerto) – bind(2) (Errn
o::EADDRINUSE)
from c:/ruby/lib/ruby/1.8/webrick/utils.rb:73:in `new’
from c:/ruby/lib/ruby/1.8/webrick/utils.rb:73:in `create_listeners’
from c:/ruby/lib/ruby/1.8/webrick/utils.rb:70:in `each’
from c:/ruby/lib/ruby/1.8/webrick/utils.rb:70:in `create_listeners’
from c:/ruby/lib/ruby/1.8/webrick/server.rb:75:in `listen’
from c:/ruby/lib/ruby/1.8/webrick/server.rb:63:in `initialize’
from c:/ruby/lib/ruby/1.8/webrick/httpserver.rb:24:in `initialize’
from c:/ruby/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/webrick_server.rb:58
:in `new’
… 7 levels…
from c:/ruby/lib/ruby/gems/1.8/gems/rails-2.1.2/lib/commands/server.rb:3
9
from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `ge
m_original_require’
from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `re
quire’
from script/server:3
Nice tutorial, thanks
It helps a lot for my new project
Thank you so much for a great tutorial. I’m working through Four Days on Rails with Rails 2 ( http://www.ultrasaurus.com/code/2008/12/getting-started-with-rails.html ) and this tutorial helped a lot.
I really liked your first post and this looks to be even better. Really cool work. Thanks.
Really neat tutorial… thanks.
Thanks for this tutorial !
very nice tutorial, thank you for your wrok
hi akita. this tutorial really helps me in understanding rails. thanks. but then i get this error after i created a comment.
ActiveRecord::AssociationTypeMismatch in CommentsController#create
Post(#-612209058) expected, got String(#-605928458)
what went wrong?
Nice Screencast and Tutorial. It is good for Ruby on rails beginner like me.
best regards
Thanks for posting these helpful informations! I have just found your website and I am a little bit overwhelmed ^^
Thanks for the nice and very useful tutorial.
this tutorial really helped me is perfect for me, Thanks
great post and Very good job, thank you for this information thanks.
webcasheuro.net
Fantastic tutorial, really well written and explained.
I am having trouble getting the comments working and was wanting to compare it against your source code but looks like it is no longer available.
This link is dead: http://www.akitaonrails.com/assets/2007/12/12/blog_demo.zip
i got this all working. if you need help, email me: anthonynonso (gmail)
Cheers!
Really it is a great tutorial.
I have developed a generator to do all the work of nested routes for you :)
You can visit it here http://rubyforge.org/projects/nestedrestscaff/n...
Really, I look forward to hear your opinions and comments
One question:
The Link
<%= link_to 'Comments', post_comments_path(@post) %>
you have added in app/views/posts/show.html.erb
will display all comments. Even the comments from another Post. What do I have to so for displaying only the comments belong to the post?