Day 3: 2nd walkthrough
After completing my first walkthrough and rails application, it is time for a little more intensive walkthrough to make sure I am understanding the architecture of ruby and rails.
The guide starts right away with the traditional guide question of “What is Rails?” I’m starting to see some themes in ruby/rails descriptions like DRY (Don’t Repeat Yourself), “Ruby is, most of all, FUN!” but this is the first time I’ve seen Rails referred to as an opinionated language. Interesting. Rails seems to be about using conformity and strict standards to solve problems as opposed to hacking away and finding the quickest solution. This sections best sums up why I am so excited to start using Rails:
Convention Over Configuration – means that Rails makes assumptions about what you want to do and how you’re going to do it, rather than requiring you to specify every little thing through endless configuration files.
I have essentially taught myself any programming languages I know (C, Java, Flex/Flash, PHP, etc) so learning new ones often means finding ways for my brain to make associations to things I already know or understand. For example, if we were in the 60’s and PHP is the land of anything goes (damn hippies), then Rails would be the land of faceless corporate suits. This is how my brain works. Anyways, back to the walkthrough, you were saying something about MVC?
Ahh, here we go. I kept noticing in the other walkthrough references to “Action …” or “Active …” but never really knew what they were talking about. We start to break down each of these components now. The Action Pack (Action Controller, Action Dispatch, Action View) seems well thought out to me. I’ll probably have to keep referencing this until I blindly know where everything should be stored but that is a minor speedbump. The Action Mailer seems useful as well and can’t possibly be worse than PHP’s mail(). I can’t wait to have all my CRUD functionality taken care of automatically by the Active Record component and using Active Resource for any web services should be fun too. Active Support is a great concept, I’m curious to see how well it is implemented. And finally, Railties. Really? If you are going to walk that line of clever names for components, you should just own it. Don’t drop one in here and there to be cute.
The walkthrough does a quick overview of REST and how it applies to Rails but they link to an article that does a much better job of giving you a full overview of REST if you are in need of something like that. I highly suggest reading it for fun as you may pick up one or two new things like I did.
Alright, coding time! Let’s make a web blog!
Moochacha:~ $ rails new blog
One command and my new app is already framed. Man, I’m not sure that will ever get old. I think I like this walkthrough better than the first as I feel like I’m learning more “why” than “how”. For example, I now am fully aware of the purpose of a Gemfile, understand the purpose of each folder in directory structure, and the difference between what is supposed to be in the README.rdoc and what is supposed to be in the doc. All of this can probably be assumed but explicitly stating it is always useful for beginners like me.
Something else that slipped by me before is the automatic breakout of development, test, and production database environments. I think of all the time I’ve wasted in previous projects getting this setup (usually after the fact) and it makes my head hurt.
Even though “-T” seems counterintuitive for essentially a help command, this is a very useful list:
Moochacha:blog $ rake -T (in ~/src/rails/blog) rake about # List versions of all Rails frameworks and the environment rake db:create # Create the database from config/database.yml for the current Rails.env (use db:create:all to create all dbs in the config) rake db:drop # Drops the database for the current Rails.env (use db:drop:all to drop all databases) rake db:fixtures:load # Load fixtures into the current environment's database. rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false). rake db:migrate:status # Display status of migrations rake db:rollback # Rolls the schema back to the previous version (specify steps w/ STEP=n). rake db:schema:dump # Create a db/schema.rb file that can be portably used against any DB supported by AR rake db:schema:load # Load a schema.rb file into the database rake db:seed # Load the seed data from db/seeds.rb rake db:setup # Create the database, load the schema, and initialize with the seed data (use db:reset to also drop the db first) rake db:structure:dump # Dump the database structure to an SQL file rake db:version # Retrieves the current schema version number rake doc:app # Generate docs for the app -- also availble doc:rails, doc:guides, doc:plugins (options: TEMPLATE=/rdoc-template.rb, TITLE="Custom Title") rake log:clear # Truncates all *.log files in log/ to zero bytes rake middleware # Prints out your Rack middleware stack rake notes # Enumerate all annotations (use notes:optimize, :fixme, :todo for focus) rake notes:custom # Enumerate a custom annotation, specify with ANNOTATION=CUSTOM rake rails:template # Applies the template supplied by LOCATION=/path/to/template rake rails:update # Update both configs and public/javascripts from Rails (or use just update:javascripts or update:configs) rake routes # Print out all defined routes in match order, with names. rake secret # Generate a cryptographically secure secret key (this is typically used to generate a secret for cookie sessions). rake stats # Report code statistics (KLOCs, etc) from the application rake test # Runs test:units, test:functionals, test:integration together (also available: test:benchmark, test:profile, test:plugins) rake test:recent # Run tests for recenttest:prepare / Test recent changes rake test:uncommitted # Run tests for uncommittedtest:prepare / Test changes since last checkin (only Subversion and Git) rake time:zones:all # Displays all time zones, also available: time:zones:us, time:zones:local -- filter with OFFSET parameter, e.g., OFFSET=-6 rake tmp:clear # Clear session, cache, and socket files from tmp/ (narrow w/ tmp:sessions:clear, tmp:cache:clear, tmp:sockets:clear) rake tmp:create # Creates tmp directories for sessions, cache, sockets, and pids
I’m loving the idea of the routes.rb file acting as the router for the application, very handy! I’ll have to dive into the routing guide later, that should be pretty useful to know.
Alright, now on to setting up the scaffolding. This is probably my shakiest part so far as there seems to be a lot going on so hopefully this walkthrough goes a bit more in depth and explains the process in clearer manner. Let’s see if I have this straight:
Moochacha:blog $ rails generate scaffold Post name:string title:string content:text
Basically means that I am generating CRUD functionality (both UI and backend) for “Post” which is essentially just a database table with name, title, and content as columns. It is also automagically generating a migration script (up AND down) for the new table, which I must run to physically create the table. Sound about right? Please correct in the comments or via twitter if not.
Moving on, my first interaction with the link_to method. The guide wants to link_to my posts/blog by providing the posts_path, but I cannot see where that is defined in the code. Is this automatically handled somewhere? Maybe just goes to the index of “posts” by default?
Looking at the app/models/post.rb file I see that “Post < ActiveRecord::Base” is syntax for inheritance. I’m not sure yet if using symbols like “<” are better than words like “extends” but it seems like semantics at this point.
Another area that this walkthrough seems superior is how it dives into the code in the posts_controller.rb file and explains what each section is actually doing. Very useful for me. In the overview of the app/views/posts/index.html.erb looping, I finally get my answer from before:
edit_post_path and new_post_path are helpers that Rails provides as part of RESTful routing. You’ll see a variety of these helpers for the different actions that the controller includes.
Sweet, makes sense. I also get this little nugget of information just after:
In previous versions of Rails, you had to use <%=h post.name %> so that any HTMLwould be escaped before being inserted into the page. In Rails 3.0, this is now the default. To get unescaped HTML, you now use <%= raw post.name %>.
Once again, crap I had to spend time dealing with before is taken care of automatically. I think I’m beginning to swoon.
Partials is a cool concept that applied to a form seems incredibly speedy and useful. Again, the amount of time I have spent coding up a form so it can be reused as both a “new” and “edit” form is incredible. I appreciate all of this auto-generated stuff, but I really wonder how is automatically handled in a real-world application. Also, what about forms that span multiple tables, how difficult is it to wire those up properly? Any rails developers care to share a little insight there? (update: this is mostly covered later in the walkthrough but I’m still curious about others opinions)
The Flash. Sounds awesome, but this walkthrough glosses over it. Must make a point of reading up on the Flash. Also, I need to look deeper at the .find method as well as the params() call.
Time to add a second model (yay!) to the blog which is the ability to comment on posts. This should help show how you can have relational databases with this setup and possibly even setting up foreign keys. Ahh yes, the “belongs_to” line sets up an association. Even better, I will apparently learn a lot about associations in the next section so lets just let that lie for now.
I’m noticing a trend in this walkthrough of repeat the phrase “Rails is smart enough to…” Kinda refreshing to be dealing with a language that is smart enough to do things.
I now see you have to backtrack and add in a reference to the model of whatever table you are associating with. Reading that back, it sounds really confusing but assuming you have the syntax down, its quite logical. Having the ability to automatically call @post.comments for an array of comments is also quite amazingly easy and useful.
Now I’m wiring up the comments in the views of the blog. It says we will be handling SPAM comments, I’m curious how this will happen as I assume it is some built-in functionality (sweeeet).
I won’t rehash the example here but I will say that the walkthrough does a good job explaining the way associated tables can be utilized in rails. I feel like more of this process could be automated but I’m very impressed with that is available out of the box.
We are on to add functionality for deleting comments manually (no auto-spam feature in this walkthrough). You know you are learning a good language when you can pretty much write your own “destroy” action on day 3 without having to peek at the walkthrough. Also, I like everything about this :dependent option on the post model
Ooooh, Security now - finally something more real-world oriented. Fairly straight forward. I like that the language and naming conventions Rails uses are all self-explanatory and just seem to make sense. Authentication works but I’m curious how you handle logouts. I guess we save that for another time since we are off to build a tagging mechanism.
When adding the view for tags, I come across the line @post.tags.map { |t| t.name }.join(“, ”) and my eye starts twitching from having to parse through giant chained commands like that in Java. Luckily, the walkthrough creator probably had a similar thing happen and so they jump right in to creating View Helpers. It doesn’t remove the idea of chained commands but it at least gets them out of the view and into their own section. I call that a win.
And after a couple Gotcha’s and further references, we have completed walkthrough #2 for Rails. Hooray! Also, I have just built a functional blog with tagging and commenting in about 1 hour or so. I can really start to see why everyone is raving about Rails and Ruby, it really does make things much easier!
Recap Ruby Comfort Level: Novice Duration: ~1.5 hours Accompaniment: iTunes random Time of Day: 6pm












