5 minute project in Rails
August 8, 2009
Ok, you’ve installed the Ruby on Rails and you want to run a quick tutorial to see what can be done. Let’s do a simplified Journal application that allows to create users & posts.
1. Create a new rails project by running a rails name_of_the_project command, like this:
rails journal
You will see a bunch of “Created xxx” messages, that will create or copy over a bunch of directories and files.
2. Next, let’s create a Scaffold for our users. Scaffold is a basic structure of Model, View and Controller that allows you to quickly create, edit, show and delete objects. Let’s assume that each user will have a name, a biography and email for now. We will use a generate script in order to automatically prepare all required files for us. Here’s the command:
ruby script/generate scaffold user name:string bio:text email:string
3. So, in the step before we have created a User model, user controller and user views for each of the basic functions of create, edit, show and delete.
The model now consists of three attributes which will be recorded in the database columns, named name, bio and email. In your Rails code you will access those attributes by something like @user.name, @user.bio or @user.email.
However, the generate script does not create the model in the database, it just creates the migration file in the db/migrate folder of your project. You can check out the directory to see that a file create_users.rb (with a timestamp in front) is actually there. If you will need to extend the model later, it can easily be done by running another migration.
Ok, let’s run the migration by typing the command:
rake db:migrate
4. Now, run the server to check that everything works as expected:
ruby script/server
And try out the following address: http://127.0.0.1:3000/users
It should show you an interface to create / edit / delete users
5. Let’s then create a model for our posts. Here’s the same command we used for creating users:
ruby script/generate scaffold post title:string post:text
And, as before, you need to modify the database by running a migration:
rake db:migrate
6. Now, we want to be able to merge these two models together. What we want to say is that a User can write (have) many posts and each post has to be written by a (belong to) user. This is very simply done in the model definitions:
In app/models/user.rb add has_many :posts association
class User < ActiveRecord::Base has_many :posts end
In app/models/post.rb add belongs_to line:
class Post < ActiveRecord::Base belongs_to :user end
Now Rails knows that Posts and Users are related and you should be able to get a list of posts of a particular user by simply typing @user.posts and vice versa – an author of the post will be @post.user. This is really cool!
Before it all works, however, you need to provide Rails with a place in the database to store the relationship. It’s done by including the id of user to the Post model (you don’t need to store / modify anything in the User model). The notation Rails follows is [related_model_name]_id, in our case user_id. And then Rails will be able to do all the wonderful relationships.
You can use the already used generate script, but this time a command migration will be used:
ruby script/generate migration add_user_id_to_post user_id:integer
And run the migration again (you should start to get used to that command by now):
rake db:migrate
7. Now it’s time to modify our default views to take advantage of the new relationship. First, let’s show the author’s name of the post. Go to app/views/posts/show.html.erb and add lines 6-9 to it.
<p> <b>Title:</b> <%=h @post.title %> </p> <p> <b>User:</b> <%= link_to @post.user.name, @post.user %> </p> <p> <b>Post:</b> <%=h @post.post %> </p> <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %>
Let’s analyze what this command does – link_to @post.user.name, @post.user
First, I already mentioned that you can get the author by accessing @post.user. @post.user is actually an instance of user and you can access any attributes of user, so in order to get the name of the user you write @post.user.name. link_to is a clever method that allows you to create a link to a controller or object. The first parameter is the title of the link, the second is the url. As link_to is a smart method, you can simply pass an instance of a class to it and it will figure out how to link to it.
8. Now, let’s show all posts of a user when you show a user. For that we need to modify the user’s show view (app/views/users/show.html.erb), adding lines 16-23:
<p>
<b>Name:</b>
<%=h @user.name %>
</p>
<p>
<b>Bio:</b>
<%=h @user.bio %>
</p>
<p>
<b>Email:</b>
<%=h @user.email %>
</p>
<p>
<b>Posts:</b>
<% @user.posts.each do |post| %>
Post: <%= link_to post.title, post %><br/>
<% end %>
<%= link_to "Create new post", new_post_path %>
</p>
<%= link_to 'Edit', edit_user_path(@user) %> |
<%= link_to 'Back', users_path %>
Ok, this one took 4 non-HTML lines, let’s go one by one:
@user.posts.each do |post| — we access the array of user’s posts and iterate through each of them by using iterator each. each is the easiest way to go through all the object in an array. The iteration passes control to block and puts each element one by one of array in local variable post.
link_to post.title, post — this is almost the same as we did for post’s user earlier.
end – this is to say to Rails that it’s the end of the iteration block
link_to “Create new post”, new_post_path — By this line we allow a new post to be created. First parameter is the string for a name of the link, second – is again a cool way to link to action of a controller [action]_[controller]_path
9. Finally, when we create a new Post we need to be able to select who is the author of the post by selecting the author from the list of available authors. In app/views/posts/new.html.erb before the lines <p> <%= f.submit ‘Create’ %> insert the new field:
<p>
<%= f.label :user_id %><br />
<%= f.collection_select(:user_id, User.find(:all), :id, :name, {:prompt => true}) %> </p>
</p>
The first line simply creates a text label of the field. The second creates a drop down list of all users in your system. The most important are the first 2 parameters – :user_id, which tells the form which variable to store the result of selection in and User.find(:all), which provides a list of all users to the drop-down.
10. Now save all changes and run the application at http://127.0.0.1:3000/users
This is an impressive application given that it took you only 5 minutes, 15 lines of code and couple of command-line commands. Of course, you will need to extend it with a proper user authentication and you will want to modify models and views to make the app useful, but it’s a great start.
Entry Filed under: Uncategorized. Tags: 5 minute project in Rails.
6 Comments Add your own
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed
1.
Installing Rails on Windows (3 years later) « All About Ruby | August 8, 2009 at 8:49 pm
[...] you should be dying to do something useful in Rails. As a very basic example you can follow this 5 minute Rails tutorial. Possibly related posts: (automatically generated)My Ruby on Rails dev environmentRails books in [...]
2.
Gaby | August 30, 2009 at 11:34 am
Just wanted to say THANK YOU!! I found your tutorial of how to install Ruby on Rails for Windows fabulous (I didn’t need to do the fix of 4.1, by the way) and just now I’ve completed this 5-minute project. I can’t wait to dig my teeth into RoR some more.
One question though. When I want to make an app live (not just on 127.0.0.1/whatever), what documents do I need to upload? And how is the whatever determined? I have a feeling it is linked to certain variables (and maybe the Scaffold), but I’m confused on the connection.
Thanks again on a great resource. I’m glad you’ve started using it again. I know what it’s like, I need to finish a blog entry of my own, heh.
3.
allaboutruby | August 30, 2009 at 3:15 pm
Hi Gaby –
1 – You will need to move almost all of your full project directory, not only the app subdirectory.
2 – /whatever is by default the name of your controller. However, if you want to be able to just go to 127.0.0.1:3000 and automatically call the “whatver” controller, you need to go to config/routes.rb and define a root route like this –
map.root :controller => “whatever”
4.
Gaby | August 30, 2009 at 9:57 pm
Almost all? What do I leave out?
Thank you for your quick response!
5.
Sarah | October 21, 2009 at 12:18 am
It took a lot more time for me but that was a lot of fun.
Framework looks amazing and programming looks like playing a toy.
I think when I’ll go deeper into this… when I’ll know more of ruby… then it will become harder.
The more I know, The less I know.
Is creating app like Twitter (let’s say like Twitter on the beggining of existence) in RoR a extremely hard task?
6.
allaboutruby | September 2, 2009 at 10:14 pm
Gaby – it depends on your situation, but most probably you won’t need the old db migrations (migration don’t migrate data) nor development log or docs in production. Everything else can go there.