Ruby on Rails – ODIN Project – 6

odinAPIs, Mailers and Advanced Topics

This final section will take you into some of the more interesting sides of the Rails ecosystem which will help you reach beyond your own app and into the lives of your users via email or harness the powers of other apps via their APIs.

Step 1:

APIs and Building Your Own

Rails is really just an API itself… learn about APIs and how to turn your app into one

API Basics and Building Your Own

Introduction

Working with APIs is awesome and frustrating at the same time. On the one hand, interfacing with other applications out there can greatly improve the reach and “cool factor” of your own app. On the other, it involves lots of reading through documentation, figuring out authentication strategies, and parsing bad (or nonexistant) error messages.

Backing up, if you’re still unclear on what an API (Application Programming Interface) basically is, read the Skillcrush explanation and then read the first bit of this article to catch up.

“API” is an incredibly broad concept — any time your application talks to another application, that’s via some sort of API. The components within your own application, e.g. the different pieces of Rails, also talk to each other via APIs… they are more or less independent sub-applications that pass along the data they each need to complete their particular task. Everything’s an API in application-land!

When you build applications that have more dynamic front-end functionality (as complicated as single page Javascript applications or as simple as individual AJAX calls), they will talk to your Rails backend via your own APIs… which is really just an extra line or two of code to tell your controllers how to spit out JSON or XML instead of HTML.

In this lesson, we’ll cover how to build your own API. In the following lesson, we’ll cover how to interface with the APIs of other applications. The lessons are meant to give you a good onramp to learning this stuff but couldn’t possibly cover all the cases. Much of working with APIs is learning to read their documentation and figure out what they want.

Points to Ponder

Look through these now and then use them to test yourself after doing the assignment

  • How Rails knows which type of file you are expecting back when you make an HTTP request.
  • What is the purpose of the #respond_to method?
  • How do you return a User object but specify that you don’t want to include certain attributes (i.e. you can’t just return User.first)?
  • What are the two steps performed behind the scenes by the #to_json method?
  • How do you tell a controller action to render nothing but an error message?
  • How do you build your own custom error messages?
  • Why can’t you use session-based controller authentication methods if you want people to access your API programmatically?
  • What is “Service Oriented Architecture?”

API Basics

Your Rails application is basically already an API, though you may not think of it that way. The web browser your user is running is also a program, so it is effectively making an API request to your Rails app whenever you request a new page. It just so happens that rendering HTML payloads is so common that we just bake that into our server-side programs as the default response type and consider everything else special.

Often, though, you want to make a request that doesn’t need to go through all the headache of using a web browser. You may not care how the page is structured (HTML), but instead just want to get straight to the data. Say you want to get a list of all users. You could go to something like http://yourapplication.com/users which will probably run the #index action and render a list of all the application’s users.

But why bother with all that extra stuff if all you want is the user list? The easiest thing to do would be to submit a request to that same URL asking for a JSON or XML response instead. If you set up your Rails controller properly, you will get back a simple JSON array object containing all the users. Sweet!

The same principle applies if you’re talking to external APIs… say you want to grab a user’s recent tweets from Twitter. You just need to tell your Rails app how to talk to Twitter’s API (e.g. authenticate yourself), submit the request, and handle the bunch of tweets that get returned.

Building APIs

You might want to make your Rails application entirely into an API backend for a front end webpage or you might just want to learn how to send out JSON when your front end requests it. This section won’t cover how to build a full featured RESTful API with authentication features… it is a gentle introduction to treating your application as an API.

The Basics

If you want your Rails app to return JSON instead of HTML, you need to tell your controller to do so. The cool thing is that the same controller action can return different things depending on whether your user is making a normal request from a browser or an API call from the command line. It determines which type of request is being made based on the extension of the file asked for, e.g. example.xml or example.json.

You can see which file type Rails thinks you want by checking your server log:

  Started GET "/posts/new" for 127.0.0.1 at 2013-12-02 15:21:08 -0800
  Processing by PostsController#new as HTML

The first line tells you which URL was requested and the second tells you where it’s going and how Rails is processing it. If you use a .json extension, it looks like:

  Started GET "/posts.json" for 127.0.0.1 at 2013-12-04 12:02:01 -0800
  Processing by PostsController#index as JSON

If you’ve got a sample application running, try going to different URLs. If your controller isn’t ready for them, you may get an error, but you should be able to see what Rails thinks you’re asking for.

Rendering JSON or XML

Once you’ve decided that you want to respond to a request for JSON or XML, you need to tell your controller to render JSON or XML instead of HTML. The way to do so is by using the #respond_to method:

    class UsersController < ApplicationController
      def index
        @users = User.all
        respond_to do |format|
          format.html # index.html.erb
          format.xml  { render :xml => @users }
          format.json { render :json => @users }
        end
      end
    end

In this case, #respond_to passes the block a format object, to which you can attach the appropriate rendering call. If you do nothing, html will render using the default Rails template as normal (in this case, app/views/index.html.erb).

The #render function is smart enough to know how to render a wide range of formats. When you pass it the key :json, it will call #to_json on the value, in this case @users. That will make your Ruby object(s) into JSON strings, which can be transmitted to the requesting application.

And just like that, you’ve got yourself an API. Of course, things can get a bit more complicated if you want to do unusual things, but that’s the basics.

Specifying Attributes to Return

Let’s say you want to make sure you don’t return the user’s email address with the User object. In this case, you’ll want to edit which User attributes get returned by modifying what the #to_json method does.

In the old days, you’d just overwrite your own version of #to_json but these days you don’t need to do that — you will actually overwrite the #as_json method instead. The #as_json method is used by #to_json, so modifying it will implicitly change the output of #to_json, but in a very specific way.

#to_json does two things — it runs #as_json and gets back a hash of attributes which will need to be rendered as JSON. Then it will actually perform the rendering into JSON using ActiveSupport::json.encode. So by modifying #as_json, you’re more specifically targeting the part of the #to_json method that you actually want to change.

In our case, we’ll do this by modifying #as_json in our model to return only the attributes we want:

    # app/models/user.rb
    class User < ActiveRecord::Base

      # Option 1: Purely overriding the #as_json method
      def as_json(options={})
        { :name => self.name }  # NOT including the email field
      end

      # Option 2: Working with the default #as_json method
      def as_json(options={})
        super(:only => [:name])
      end
    end

In our controller, we then just need to render JSON as normal (in the example below, it will just always return JSON, whether it’s an HTML request or not):

    # app/controllers/users_controller.rb
    class UsersController < ApplicationController

      def index
        render :json => User.all
      end
    end

Note that you don’t need to call #to_json yourself when using #render… it will do it for you.

See the as_json documentation for details and more, like how to include associations.

Rendering Nothing or Errors

Sometimes you just want to send out an HTTP error code without any response body. The web is conflicted about the best practices for doing so (see This older blog for one approach or this SO answer for another set of answers) . Here’s a simple example (again we are just rendering the error in all cases):

    # app/controllers/users_controller.rb
    class UsersController < ApplicationController
      def index
        render :nothing => true, :status => 404
      end
    end

Creating Dynamic Error Pages

You can create your own error pages. See this blog post.

Sometimes Heroku can require additional steps to properly display your error pages. See their error page docs here. You might need to delete the static pages in the app/public directory first.

External Facing Security

Let’s say you want to only allow an API call if your user is logged in. Your existing controller authentication will work to cover this as well — just make sure you’ve got the right #before_action set up (e.g. before_action :require_login). This might be the case if both logged in and non-logged-in users will be viewing the page but each should see different data. You don’t want your not-logged-in-users to be able to make API requests for sensitive data just like you wouldn’t want them to be able to visit an unauthorized HTML page.

If you want to handle requests from an application that isn’t a web browser (e.g. the command line), you can’t rely on browser cookies to authenticate you. That’s why most APIs issue custom tokens to each authorized user which must be sent along with the request as part of the authentication process. We’ll talk a bit more about tokens in the next lesson.

Next Steps

Right now you’ve got the ability to use your Rails app to serve up not just HTML but also whatever formats you want. If you’d like to take this further and allow other developers to build on your platform (so they’ll be making programmatic requests instead of logging in as users), you’ll need to make your API system far more robust. We won’t cover it all here, but check out the following:

Service Oriented Architecture (SOA)

This is a good time to introduce an architectural concept called “Service Oriented Architecture”. The basic idea is that your application will likely have many different services within it, for instance the payments processing, user registration, recommendation engine, etc. Instead of building all of these under the same master application, you break them out into fully independent pieces and have them talk to each other using internally facing APIs.

This is good for many reasons. Because each piece of your application doesn’t care how the other pieces work and it only knows how to ask for data via their APIs, it allows you to make major changes to the code within a service and the rest of your application works just the same. You can completely substitute one service for another and, as long as it communicates using the same API methods, it’s easy. You can use an external API for a part of your app (like payments) instead of an internal one. You can have a PHP app talking to a Python app talking to a Rails app and no one cares since they’re all communicating using APIs

It’s usually a good idea to strive to keep independent pieces of your application as independent as possible anyway. Formalizing this under the umbrella of SOA forces you to think in terms of exactly which methods you want to expose to the other parts of your application and it will make your code better along the way. An added benefit is that, when you assume that each major component of your application is independent, you can also isolate issues much easier and will be forced to handle errors in a reasonable way.

Using an SOA architecure for your whole application is sort of like breaking up a giant and complicated Ruby script into nice neat classes and methods, just on a broader scale.

One of the best known cases of switching to a service-oriented architecture was Amazon.com. Sometime in 2002, Jeff Bezos basically dictated that every group would switch to SOA or be fired. An infamous blog post from a Google Employee, accidentally released to the public instead of staying internal to the company, talked about Amazon’s strength with SOA. It’s a great read so check it out, but the basics of Bezos’ email are, as quoted from the post:

1) All teams will henceforth expose their data and functionality through service interfaces.

2) Teams must communicate with each other through these interfaces.

3) There will be no other form of interprocess communication allowed: no direct linking, no direct reads of another team’s data store, no shared-memory model, no back-doors whatsoever. The only communication allowed is via service interface calls over the network.

4) It doesn’t matter what technology they use. HTTP, Corba, Pubsub, custom protocols — doesn’t matter. Bezos doesn’t care.

5) All service interfaces, without exception, must be designed from the ground up to be externalizable. That is to say, the team must plan and design to be able to expose the interface to developers in the outside world. No exceptions.

6) Anyone who doesn’t do this will be fired.

SOA is a big deal. There are certainly a lot of issues that crop up when you’re using it — see this post on Amazon’s “lessons learned” — but it ultimately has a lot of benefit.

You probably won’t be worrying too much about SOA while building “toy” applications for yourself but it will certainly come up if you find yourself working at a tech company and it’s a good principle to become familiar with.

Your Assignment

  1. Read the Rails Guide on Controllers section 7 to learn about rendering JSON and XML.
  2. They are not required viewing (because they get a bit deeper than we’re scoped for), but if you’re interested, go check out the Railscasts in the Additional Resources section at the bottom of this lesson for more API goodness.

Conclusion

We’ll get more into using your application as an API during the course on Javascript. In that course, you’ll build some full stack apps that use Javascript AJAX calls to smooth out the user experience, which basically involves asking your Rails app for some XML or JSON data instead of a full HTML page. Then you’ll get to build some single page Javascript apps which rely on the API provided by your Rails app for all the necessary database data but otherwise completely run the show on the front end.

The best way to really figure out APIs is to build them and interface with them, so we’ll focus on that in the projects.

In the next lesson, we’ll cover working with other people’s APIs, which can add all kinds of firepower to your own application.

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something


 

Step 2:

Working With External APIs

Lots of the power of APIs comes from interfacing with third-party applications, which we’ll cover in this lesson.

Interfacing with APIs

Introduction

It’s pretty easy to turn your application into an API, but what about grabbing data from other APIs across the internet? That’s where things usually get a bit more challenging because they’re all different and you’ve got to authenticate yourself.

Most popular services offer APIs so developers can interface with them (they love it if you can get more people using their platform). Facebook, Twitter, Instagram, Flickr, Dropbox, AirBnB… They’ve all got APIs. Just Google “companyX API docs” and you’ll get to their developers section.

If you go to the documentation for an API, it can sometimes be a bit overwhelming because much of the material sort of assumes that you know what you’re doing, but some are definitely better than others. There are also elements that are common across almost all of them. The more you work with APIs (and get the hang of the authentication flow), the easier they get. You’ll be making mashups in no time.

This lesson will cover some general steps that are common across APIs and will do high level overviews of some of the methods for authenticating with APIs like Omniauth. Try to gain as much conceptual understanding as you can here and use the documentation each gem or API provides to help with the implementation. If you find great free learning resources that explain APIs, please let us know (try using the suggestion box at the bottom of the page)!

Points to Ponder

Look through these now and then use them to test yourself after doing the assignment

  • What’s the best way to locate an API’s docs?
  • What are the steps you’ll almost always have to go through when setting up your app to use an API?
  • What is an API key?
  • How is API use typically controlled?
  • How do you avoid including an API’s secret token in your Github repo (e.g. hard coding it)?
  • Why is it important to know which API version you’re using?
  • What is a RESTful API and why does that make your life easier?
  • What (basically) is OAuth?
  • Why would a user prefer to sign into your site using Facebook instead of giving you a new password?
  • How (basically) does this process work from the user’s perspective?
  • How (basically) does this process work from your (the application developer’s) perspective?
  • What are the basic rules of thumb for not abusing APIs?
  • What is OmniAuth and why does it save you tons of time/pain?
  • What is an SDK and why are they useful for working with APIs?

First Steps

You will need to register yourself and your application with the API provider. They will track and monitor your usage this way. Typically, there is a free tier of usage and it will cost you if you’re going over your limits, whether they are expressed in terms of total MB downloaded, number of requests, or number of transactions (for instance). Usually, even if you’re a user of their service, you will need to separately go to their developer portal.

You will need to get an API key from the API provider, which often is the last part of registration. This key will uniquely identify your application to the API provider and you will send it along with every request. It’s sort of like a user on your site automatically submitting their session cookie with each request so you know they’re logged in.

You’ll typically also get a “secret key” or similarly named code. Whereas the API key is usually public, the secret key is an added layer of security that’s required for the more secure APIs and you will use it to generate a cryptographic token that authenticates any requests you make. You will need to make sure you don’t include this secret key in your Git repo! Use the figaro gem or environment variables to put the key on the server instead of hard coding it.

API Rates and Security Tokens

Most APIs require a different type of “security clearance” for different requests:

  1. You can usually make innocuous requests like asking for Tweets (with Twitter’s API of course) with straightforward and unauthenticated GET requests. You can make these from any command line or a browser tool like Chrome’s Rest Client. These types of API requests are usually severely rate limited to incentivize you to sign up.
  2. The next layer is making requests that include your API key. These are still usually fairly innocuous things (like getting public data) and limited by the API’s pricing tiers.
  3. More sensitive requests like asking for specific user data or submitting/modifying/deleting data will likely require you to use an authentication process involving your secret token. We’ll cover the basics of this in the project. Rates for these requests are subject to the API pricing tiers.
  4. Oftentimes, you actually want to make requests on behalf of a user. For instance, showing a user a dashboard of all his tweets and Facebook posts together would require asking Twitter for that user’s tweets and Facebook for that user’s posts. This can involve a LOT of requests over a large user base, but luckily you’re actually able to make them on the user’s behalf by asking for the user’s permission. We’ll cover this as well later, but basically you send the user to the API provider’s site to sign in, then the API provider will give you a user-specific token to use when making requests on their behalf in the future. Rates for this are usually more advantageous because they are covered in a per-user bucket. We typically use the OAuth protocol for this, as described below.

Versions

Tech companies, especially if they’ve been around for a while, typically have several versions of their API. Usually, they built a first draft version when they were a startup and then had to build a real one later, but still have to support the original since so many other applications are likely to be using it.

Just go for the latest version unless you have a compelling reason not to (it’s usually got a separate section of documentation for each version). Pay attention to which version’s docs you’re looking at… there’s nothing like the frustration of realizing you’ve been looking at the v1 API instead of the v2 API docs.

RESTful APIs

Just like your routes should ideally be set up in a RESTful way, so too should APIs. These days, most APIs are RESTful, meaning the usual batch of GET/PUT/PATCH/DELETE requests will retrieve resources as expected. The good part about setting up your application routes RESTfully is that your API will be the same way.

Working with RESTful APIs at least takes a lot of the headache out of the process since you can usually sort of guess what you should be doing, then can head over to the docs to figure out how exactly and what format you’ll get the results back in. For instance, just like you’d expect the GET request to the /users route in your app to display a page listing all its users, a GET request to a RESTful API for the same route should probably give you back a JSON or XML object filled with all the users (or at least some paginated sample of them).

Oauth and Login via API

You’ve seen sites where their homepage lets you log in using Facebook or Twitter or LinkedIn. After logging in with one of those third-party services you magically have a new account with them but don’t need to give them a new password.

OAuth is usually behind this. It solves the very real problem of user data privacy and access control. The idea is that the user shouldn’t need to give your awesome application their password in order for you to make requests on their behalf. So OAuth allows Facebook to act as a sort of intermediary when dealing with the user.

This has two great use cases — logging in the user with an external site like Facebook and making requests for or submissions of data on the User’s behalf.

In the first case, you never actually discover the user’s Facebook password. They get redirected to Facebook’s website to sign in, where they authorize you to use some of their data (which you’ll have to configure when you set up this process). Facebook then calls you back (by sending a request to a URL of your choosing with the proper data) and gives you a special access token for that user. You can then use that to get any additional data that the user has authorized you to access (like their name and email address). Now you can create a new user in your database with that data and everyone’s relatively happy.

From the user’s perspective, they only need to remember their Facebook password to log into your site so it’s easy for them. They also don’t need to trust you with their password. As long as they trust Facebook, they can use your site. Also, if your site is doing bad things with their data (like when SocialCam spammed the hell out of everyone’s Facebook timeline for a while), they can tell Facebook to stop allowing you to use their data and Facebook will turn off access for the token they gave you.

From Facebook’s perspective, they retain majority ownership of the user and nestle deeper into everyone’s lives (for better or for worse).

Once you have the user token, you are allowed to make requests or submissions based on whatever permissions Facebook (and the user) authorized you to. That could involve asking who their friends are, posting on their timeline, or “liking” something. You just need to include the token as a part of your authentication process for the request.

Restrictions

Every site, in addition to rate limiting their API, will have terms of use. This usually covers what you’re allowed to do with the data you gather. For instance, they probably aren’t going to allow you to store a whole bunch of their data in your own database (harvesting). They also probably won’t allow you to do anything SPAMmy or which will hurt their user’s experience. Common sense should be your initial guide, but consult the TOU documentation for specifics. Basically, if you’ll be hurting their user’s experience or taking their precious data, you can’t do it.

It should be noted that any time you develop using someone else’s API, you’re putting yourself at their mercy. If you’re using it to the point where you pay for data, they’ll love you. If you get too successful and become competitive with them, they’ve got you by the neck and will cut you off or demand exorbitant fees. Just be cognizant of those risks.

OAuth 2.0 Basics

OAuth 2.0 is actually pretty complicated, so I’ll just cover the basic process. You don’t really need to care how exactly it works behind the scenes until you start really developing with it or trying to create your own API that uses it. You will need to understand the steps involved in the user experience because, well, the user is the reason you’re building your application.

Basically (still using Facebook as an example):

  1. User tries to access a page on your app and you ask the user to login
  2. User chooses the “Login With Facebook” option
  3. User is redirected to a Facebook page asking them to review the permissions you are asking for and telling them to sign in. The URI will contain parameters that tell Facebook who your application is and possibly which URI they should submit their response to (or maybe you specified this as a part of your API registration process with them).
  4. User decides you seem like a fun application so he’ll allow you to see his email address and post to his timeline. He signs in to his Facebook account. Facebook creates an authorization code and sends it back to your application’s callback URI.
  5. The user waits while your application takes that authorization code and uses it to ask Facebook for the real good stuff. Facebook makes sure your application is the same one the user authorized, then POSTs back to you a unique authentication token for the user (which likely expires in 90 days) and any data you asked for up front (like email address).
  6. You store the user’s unique token in your database and use it, along with your application key(s), to make any subsequent requests on the user’s behalf.

See this brief overview of OAuth 2.0 for an overview. Then check out this more substantive explanation from tutsplus.com.

Implementing OAuth 2.0 in Rails — Use Omniauth!

This sounds horribly complicated! Someone must have made a gem for it…

Luckily someone has. Many someones, actually. There is a generic OAuth gem called omniauth (docs available on Github) and then a separate gem which provides a specific authentication strategy for every major API (see the list HERE). Once you’ve gone through things with one of them, you’ll become comfortable with all of them.

I’ll leave it to the projects to walk through using Omniauth since it’s much easier to learn by doing than reading a bunch of bullet points.

SDKs

In addition to or instead of API access, many companies provide SDKs (software development kits). Usually these are Javascript libraries that contain all the code necessary to access their API. This can be useful because you’re then able to access the API with simple Javascript methods instead of doing backflips on your own backend. It comes with the downside, however, of expanding your code base and forcing you to use their conventions for everything.

We won’t cover SDKs explicitly in this course but they should be well within reach to pick up by reading the documentation.

Your Assignment

  1. Watch this Railscast on using Omniauth to allow Twitter Signin.
  2. Read through the Omniauth documentation
  3. Pick an API that you really might like to interface with or a web product you use almost every day (e.g. Google, Facebook, Instagram…). Google for its docs, e.g. with “instagram api documentation”, and have a look at them. Some docs are better than others, but they will be your source for understanding which methods you can call, what they will return, how to register your application to get an API key, and more useful tidbits.

Conclusion

APIs are fundamental to making rich web applications and they’re also a lot of fun — it makes your app feel a lot more “real” when you’re able to let your users log in using Facebook or if you can display information from different sources across the web. If you’re building a startup, it improves the user experience enough that you’ll likely see an uptick in conversion rates.

Working with external APIs can be incredibly rewarding because you’re able to leverage functionality that others have spent a lot of time perfecting but also incredibly frustrating because they’re all different and you have to rely on gems which are doing things behind the scenes that you’re not entirely sure of. Over time, you’ll start to see a lot of similarities between APIs and the procedure for working with them will feel more and more comfortable. To help get you there, the next project will have you working with an API and your final project will have you implementing signin via API as well.

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something


 

Project:

APIs

In this project, you’ll both build your own API and work with a third-party API.

Projects: Building and Using APIs

Don’t forget to use Git to save your projects!

Warmup: Exploring the Flickr API

In this warmup, you’ll get a chance to poke around with an existing API from Flickr. You’ll need to read the documentation to understand which calls to make but they have a nice API explorer tool which submits API calls on your behalf.

Your Task

  1. Head over to the Flickr API Documentation Page. You can just google XYZ API docs to locate these pages, which is usually much faster and easier than trying to find them by navigating the websites themselves.
  2. Look around at the different methods available. They have a couple of different request formats, but check out the RESTful API format by clicking on the link on the left under “Request Formats” called Rest.
  3. This shows you the format that a typical API call would take — you will make your request to the endpoint at http://api.flickr.com/services/rest/ and include any required data in the GET query string or the POST body.
  4. Look around at the various methods. How would you upload a photo? How about getting your contacts list? Lots of these methods will require you to authenticate your application or user account first.
  5. Check out the Search method docs. This request doesn’t require you to authenticate, just provide an API key (which you would get by registering as a developer on their platform). Browse through all the arguments that can be used.
  6. If you go to the bottom of the Search docs, you’ll see a link to the Search API Explorer. This tool lets you actually execute requests using Flickr’s API key for illustrative purposes. You just enter the options you want and it will make the request for you. Try entering “puppies” under the “tags” argument, then scroll to the bottom. Change the response “Output” dropdown to JSON then click “Call Method”.
  7. When the page refreshes, you’ll see your results down at the bottom. You should see a big list of photo objects (after some meta data) that were returned by your search. They look like:
        { "id": "11357337313", "owner": "84645040@N00", "secret": "6dd795c9c6", "server": "3805", "farm": 4, "title": "Gavin-Feb2013-0127", "ispublic": 1, "isfriend": 0, "isfamily": 0 },
    

    More interestingly, you can see the URL they used to make the request below that. I’ve broken it apart here to show the parameters more clearly:

        http://api.flickr.com/services/rest/
          ?method=flickr.photos.search
          &api_key=e0eb58bf4b3e29b253e86d6092e69dee
          &tags=puppies
          &format=json
          &nojsoncallback=1
          &api_sig=200efb63cb01a3d141fff12585e1e20a
    
  8. The URL contains the REST endpoint we looked at before, along with our search query and some other options like the API key and format. If you copy and paste that into your browser, you’ll see the same batch of output.
  9. If you look back on the main API docs page in the “Read these first” box, there’s a link that says URLs. Follow that link.
  10. Flickr’s API requires two steps to actually display a photo — you need to get a photo’s meta information (which we just received in our search results) and then you need to piece it together into a URL that Flickr can understand to actually retrieve the photo. The format they suggest is:
    http://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}.jpg
    

    We can plug in values from the previously retrieved photo to display a photo:

    http://farm4.staticflickr.com/3805/11357337313_6dd795c9c6.jpg
    

    Which looks a lot like:

    We could also add in additional parameters like size on the end.

  11. Tada! Every API is different and you’ve got to read through their documentation to understand the basic format of using it. Sometimes it can be helpful to search for a YouTube or NetTuts video with a quick overview as well.

Project 1: Building a Simple Kittens API

This is a fast and straightforward project where you’ll set up a Rails app to be a data-producing API… which is just a fancy way of saying that all your controller methods will render data instead of HTML. Consider this a drill in quickly building a pure vanilla RESTful resource. We won’t be working with an external API until the second project.

Your Task

HTML

We’ll start by building our Kitten application to work normally in the browser with HTML.

  1. Set up a new Rails application (odin-kittens) and Git repo
  2. Update the README to describe the application and link back to this project.
  3. Build a Kitten model with attributes of :name, :age, :cuteness, and :softness.
  4. Build a KittensController and :kittens routes for all 7 RESTful actions.
  5. Set your default route to KittensController#index
  6. Fill out each of your controller actions and their corresponding views to display a very basic HTML page — #index should just list all Kittens, #show should display a single Kitten, #new should render a simple Kitten creation form, #edit should use the same form (which should be a partial used by both the New and Edit views) to Edit the Kitten, #create and #update should do their jobs.
  7. Make a delete link on the Kitten’s Show and Edit pages, as well as next to each Kitten listed in the Index page.
  8. Implement a simple display of the flash hash (like you did in the tutorial) which congratulates you on adding or editing or deleting kittens and makes fun of you for errors in your form.
  9. Test out your Kitten creation machine to make sure all your controller actions are running properly.

JSON API

Now it’s time to make the Kittens resource available via API.

  1. Open a new command line tab and fire up IRB. > require 'rest_client' (you may need to $ gem install rest_client if you haven’t already). Test it out by making a request to your application using > response = RestClient.get("http://localhost:3000/kittens")
  2. You should get a sloppy mess of HTML. If you check out your server output, it’s probably processing as XML, e.g. Processing by KittensController#index as XML
  3. Try asking specifically for a JSON response by adding the option :accept => :json, e.g. RestClient.get("http://localhost:3000/kittens", :accept => :json). It should throw an error.
  4. Now modify your KittenController’s #index method to #respond_to JSON and render the proper variables.
  5. Test it out by making sure your RestClient calls return the proper JSON strings.
  6. Do the same for your #show method, which will require you to provide an ID when making your request. Your CSRF protection will prevent you from creating, updating or deleting kittens via the API, so it’s not necessary to implement those.

This project may seem simple, but now you’ve got a website that is both a normal HTML-producing back end AND an API that can be used to pull data from it. You could use Javascript calls from the front end to dynamically refresh your data now or even to load the whole page in the first place. Or maybe you’ll be hooking up a Kittens app to your iPhone and need a back end. It doesn’t matter, since now you’ve got a RESTful API.

Student Solutions

Send us your solution so we can show others! Submit a link to the Github repo with your files in it here using any of the methods listed on the contributing page. Please include your partner’s github handle somewhere in the description if they would like attribution.

Project 2: Using a Third Party API

Remember way back in the warm-up when you played with the Flickr API? Now it’s time for you to actually use it. Huzzah! You’ll create a simple photo widget that allows you to display photos from your Flickr feed (or someone else’s). We’ll rely on a tutorial for much of the heavy lifting but the principles of what you do here will be repeatable for use with other APIs.

Your Task

  1. Go back to the Flickr API Docs and click Create an App at the top.
  2. Follow the steps for getting your API key. You’ll have to sign in or sign up for Yahoo (someone has to these days) and give them some basic information about your app. Select “Apply for a non-commercial key” and let them know how awesome your photo feed app will be. You’ll automatically get a key generated for you, in addition to a secret key. Copy both of these somewhere you can get to them later.
  3. Use the idGettr website to look up your ID by pasting in your flickr username in the example URL, e.g. http://www.flickr.com/photos/eriktrautman/. You’ll need that later for some of the API methods.
  4. Upload a few photos to your photostream!
  5. Follow the tutorial listed at pixellatedvisions.com for building a Flickr sidebar. You’ve already completed a couple of the steps. The tutorial is old but should still work for you. It uses the flickr_fu gem, which no longer works with the Flickr API, but there are other options out there (like Flickraw). You’ll find a gem for pretty much every API out there. They will all require you to include your API keys and secret keys somehow, in this case by using the config/flickr.yml file.
  6. One note is that it’s not good practice to have your secret key hard coded into your app because then it’s hardly a secret, especially if you’re pushing to Github. A better practice is to store the key in an environment variable instead and/or use a gem like figaro (see docs). Environment variables allow you to push your key to your app directly from the command line when it fires up. Figaro operates under the same principle, though it helps you out by allowing you to store the keys in an actual file that just doesn’t get committed with the rest of your code. Use one of these techniques unless you’re a cowboy. They are well described in Daniel Kehoe’s RailsApps article.
  7. Build a simple StaticPagesController to display a home page with a simple form. The form should just be a single text field which takes the ID for a Flickr user. Once the form is submitted, the page should refresh and display the photos from that user.
  8. Modify the image feed from the tutorial’s sidebar to display in the main page body instead. This is to test how much you learned vs. copy-pasted!
  9. Ask for your friends’ flickr IDs or find random photofeeds on the web. View them in your app and react appropriately.

Student Solutions

Send us your solution so we can show others! Submit a link to the Github repo with your files in it here using any of the methods listed on the contributing page. Please include your partner’s github handle somewhere in the description if they would like attribution.

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something *


 

Step 3:

Mailers

You don’t often think about where your email comes from. Here you’ll learn how to send it from your app.

Mailers

Introduction

Email is underappreciated in its complexity on many levels. I certainly didn’t think about it much until I needed to actually bake it into my apps. But what goes on behind the scenes, especially after hitting “send”, is pretty impressive… lots of bouncing around the architecture of the internet, bypassing firewalls, and navigating SPAM filters. Luckily all this can be handled by some specialty Heroku add-ons or other third parties.

The actual production of the email is what we’ll cover here… i.e. how do you make that special “thanks for signing up, userX” email. Creating and sending email is actually conceptually similar to rendering views and shipping them to the web browser, at least from your point of view as a Rails dev. In this lesson we’ll cover that process and you’ll get a chance to send your own emails in the projects.

Points to Ponder

Look through these now and then use them to test yourself after doing the assignment

  • What is a mailer?
  • How do you set up a new mailer from the command line?
  • How are mailers similar to controllers? To models?
  • How do you pass instance variables from the mailer to the mailer view?
  • Why do you need both a text and HTML version of your mails?
  • How do you send an email directly from the Rails console?
  • How can you take advantage of add-ons and third-party programs to send email?
  • What is the letter_opener gem good for?
  • Why can’t you use *_path link helpers in mailer views?
  • How do you style up a pretty looking HTML email?

Brief Overview

To send email, Rails uses the ActionMailer gem (one of the 7 core gems that make it up). A mailer acts similar to a model and controller baked into one. You will create a new mailer just like you would with a new controller ($ rails generate mailer SomeName). You’ll then set up methods for each email that you might want it to send (e.g. welcome email, followup email, thanks for purchasing email…). Sounds a lot like controller actions, eh?

In each method, you need to identify the key fields and any variables that will be used in the text of the email (like the user’s name). The actual email itself is just a view. They live in the app/views folder along with the rest of them, though in a sub-folder named after the mailer.

One distinction between mailer views and “normal” views is that emails typically have two separate formats — HTML and text. Most people will view the HTML version but some will have HTML disabled and so they will need the text version in order to see your email. Having the two versions also helps you bypass SPAM filters. You’ll quickly find that many things you do regarding email have to do with getting past the dreaded SPAM filter.

So you set up one view called, for instance, app/views/user_mailer/welcome_email.html.erb and another called app/views/user_mailer/welcome_email.text.erb. It is kind of annoying having to manage two different versions of the same email but such is the cost of accessibility and SPAM fighting. Another thing you’ll notice is that you can use ERB (or HAML etc) preprocessing on your emails too. Just like any other view, it allows you to dynamically create content that includes things like your user’s name or non-sensitive account information. This is all based on which variables you pass the view from your mailer, just like passing a controller action’s instance variables to a normal view.

Mailers are actually a two-step process — first you build the email itself and then you call the #deliver (or #deliver!) method to actually send it. One way that mailers are different from controllers is that you call them directly instead of working through the router. When you want to call the welcome email, you will write UserMailer.welcome_email(@user), which returns the email object. Deliver it by calling the #deliver method on that object, for a total chain of: UserMailer.welcome_email(@user).deliver.

As long as your view files (the HTML and text) are named the same as your mailer methods, Rails will find everything okay and will send the email (with both the HTML and text parts) using whichever addon you’ve chosen to use for sending it. The Rails Guide reading does a good job walking through the process, so you’ll get a chance to see it in action there.

Callbacks

Mailers allow you to use callbacks just like a normal controller, for instance the after_action callback. They will run after the email is generated, not after it is sent, so you’ll be able to modify parts of the email if you need to. You get access to the instance variables of the mail instance, so you can use the @user variable as a part of your logic.

Email Addons

In the reading you’ll see how to send mail using your Gmail account, but if you’re building a real application you’ll obviously want something a bit more robust. There are several leading players in the space of sending your email for you. Their whole job is to handle getting your mail delivered and opened so you can focus on building your application. They are usually available as add-ons to Heroku (like New Relic was, which we saw in the lesson on deployment), so all you need to do is properly configure them.

SendGrid is the add-on used with this website for delivering welcome emails and the like and it’s pretty straightforward. See the documentation here, which includes instructions for how you should set up your config/environment.rb file to get ActionMailer to interface with them. You will need to use environment variables (or the figaro gem) again to avoid hard coding your password and username.

Pricing for this, as most things, is free up until a certain usage tier. While you’re building toy apps, it will do just fine. Other options out there include MailGun and PostMark, all available in the email section of the Heroku Addon Store.

You’ll get a chance to play with mailers and addons in the projects.

Letter Opener

One key thing to note is that you don’t want to fire off a bunch of emails when you’re testing your app in the development environment. That’s not just bad practice, it can make your users pretty unhappy and get you put on SPAM lists. No bueno. But you do want to make sure the email function is working properly. Luckily, there’s a simple solution which is quite useful.

The Letter Opener gem (see docs), put in your development group of the Gemfile, will take your emails and display them in the web browser for you whenever they would otherwise be sent. You just switch a config setting in your config/environments/development.rb file and you’re good to go. Sweet.

Email Wisdom

  • Email is SLOW! It can take 1-2 seconds per email to send, so don’t make your main application do it when you’re serving a whole bunch of them because then anyone trying to access it will be shut out.
  • Make sure you use full URLs in any links in your mailer (so _url not _path helper methods), since the user will be opening the email and clicking the link at an external source. In your config/environments/production.rb file you’ll want to make sure to specify your website’s host name using something like config.action_mailer.default_url_options = { :host => 'yourapp.com' }. If it’s not set, you may get an error message about your host or your links may look funny.
  • The #deliver! method will throw an error on delivery failure whereas #deliver will return false (failing silently).
  • When styling your email HTML, you won’t have access to any stylesheets so you’ll need to do all the styling either inline or using <style> tags.
  • Attaching images to emails (like using logos in the HTML version) can be a bit of a pain. See the reading.

Your Assignment

  1. Read the Rails Guide on ActionMailer chapters 1 and 2.
  2. Skim the brief chapter 3 on receiving emails. You’ll be able to refer back to it if you need to.
  3. Read chapter 4 and 5 to learn about callbacks and helpers.
  4. Read chapter 6, which covers sending mail with your Gmail.
  5. Skim chapters 7-8 on testing and intercepting emails.

Conclusion

Sending email is just a slightly different way of using the same patterns you’ve already been using for controllers and views, so it should be pretty straightforward to pick up. You’ll have to navigate the usual batch of errors when trying out new things (often related to the configuration or naming your files properly), but it’ll come to you quickly.

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something


 

Project:

Sending Confirmation Emails

Add email functionality to an existing project. Just don’t SPAM, it’s frowned upon.

Project: Ruby on Rails Mailers

Don’t forget to use Git to save your projects!

Project: Sending Welcome Emails

Setting up a mailer is a relatively straightforward task. It’s very similar to building a new controller and views. Once you’ve made a couple, it should come naturally.

Your Task

You’ll be dusting off your Flight Booker project (or one of the other projects that has users registering) and having it send out a “You have booked your ticket” email to all Passengers when they are created as part of the booking process.

  1. Locate and load up the project file.
  2. Do some pushups and jumping jacks. You’ve been spending a bit too much time at the computer lately.
  3. Generate your new mailer with $ rails generate mailer PassengerMailer
  4. Install the letter_opener gem (see docs here) to open your emails in the browser instead of sending them in the development environment.
  5. Follow through the steps listed in the Rails Guide to create the action to send the “thank you” email.
  6. Build both a .html.erb and .text.erb version of your thank you ticket email.
  7. Test that the email sends by creating a new flight booking (letter_opener should open it in the browser for you if you’ve set it up properly)
  8. Try out one other trick — call the mailer directly from the Rails Console using something like > PassengerMailer.thank_you_email(Passenger.first).deliver!.
  9. Extra Credit: Deploy it to Heroku and try it out. If you deploy to Heroku, there will be a bit of additional setup to get the SendGrid add-on (see docs) and make sure your configuration is set up properly. The docs describe how to get that up and going.

Student Solutions

Send us your solution so we can show others! Submit a link to the Github repo with your files in it here using any of the methods listed on the contributing page. Please include your partner’s github handle somewhere in the description if they would like attribution.

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something


 

Step 4:

Advanced Topics

A mash-up of orphan topics like advanced routing, layouts, metaprogramming and design patterns.

Advanced Topics

Introduction

There are some topics that we just haven’t had a chance to get into yet but will prove useful for you to know. In this section we’ll cover advanced routing, layouts, and a brief introduction to metaprogramming.

Points to Ponder

Look through these now and then use them to test yourself after doing the assignment

  • When do you need to use a singular Resource vs a plural Resources in your router?
  • What is the “missing” route when using a singular Resource? (there are only 6 when you $ rake routes) What else is missing from many of the other routes?
  • Why would you use nested routes?
  • What order do you specify their respective IDs? What are they called in params?
  • Why might you use a “member” route?
  • How are “member” and “collection” routes incredibly similar? Slightly different?
  • How do you set up a redirect route that also passes along any parameters?
  • How do you name a route using an alias?
  • Why might you want to use nested or multiple layouts?
  • How would you (roughly) go about implementing this?
  • How can you pass variables between your layouts?
  • How do you #yield to #content_for content?
  • What is metaprogramming?
  • How do you use the #send method to run a method?
  • How do you create a new method on the fly?
  • When does Ruby call the #method_missing method?
  • How can you use #method_missing to your advantage?
  • What are Design Patterns?
  • What are the SOLID principles?

Advanced Routing

You should be quite familiar by now with the bread and butter of routing — converting RESTful requests using the familiar HTTP verbs into mappings for specific controller actions (whether using the #resources method or explicitly specifying them using the get method. That’s 90% of what you’ll use your routes file for… but that other 10% gives you some pretty neat options like redirecting directly from the routes file, nesting routes inside each other, or parsing parameters from the incoming request.

Singular Resources

You might have already run into this at some point without necessarily understanding it. Up until now, we’ve been talking about resources (like “posts” and “users”) where there are a whole lot of them. It seems fairly intuitive. In your config/routes.rb file, you represent these simply with a single line like resources :users.

Sometimes there are also resources where it actually only makes sense for there to be one. An example would be a User dashboard which displays interesting facts based on whichever user is logged in. There is only one dashboard template, it just happens to be smart enough to display things that are relevant for the user who is currently logged in.

In this case, it doesn’t make a whole lot of sense to display an “index” of dashboards, since there is only one (it just changes based on who is logged in). We can also say that, for any of the other actions which would normally require an ID to differentiate which resource we’re operating on (like #show), since there’s only one, we no longer need the id parameter.

The routes file line for a singular resource would look like:

    # in config/routes.rb
    resource :dashboard

Just note that the word “resource” is singular and so is dashboard. That trips up a lot of people who make the typo of writing “resource” instead of “resources” when they really want plural resources (which are more common).

The $ rake routes for a singular resource would only contain 6 routes (since we don’t use #index anymore), and you would no longer see any of the :id portions of the routes, e.g.

  new_dashboard  GET /dashboard/new(.:format)  dashboards#new

…compared with the plural version of the same route:

  new_post  GET /posts/:id/new(.:format)  posts#new    

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something about Singular Resources

Nested Routes

Sometimes it just makes sense for one resource to be nested inside of another. For instance, a listing of lessons like this logically falls within a listing of courses — so you’d expect a URL sort of like http://example.com/courses/1/lessons/3. The way to achieve this nesting is in the routes file by literally nesting one resource inside a block given to another, which might look something like:

    # config/routes.rb
    TestApp::Application.routes.draw do
      resources :courses do
        resources :lessons
      end
    end

Note that the #resources method now takes a block which will consist of a set of routes.

When you visit the URL, you’ll have to specify the :id parameter for BOTH objects. The $ rake routes for the above would include something like:

    course_lesson  GET  /courses/:course_id/lessons/:id(.:format)  lessons#show

It should also be noted that you’re being taken to the controller of the deepest nested resource, and that’s also the :id parameter which will be called simply :id (any parent resource parameters, as in the above, will be specifically called something like :course_id).

View helpers are also automatically generated in a logical way (as you can see in your $ rake routes output). When you use view helpers like #course_lesson_path you will need to specify both parameters in order, e.g. course_lesson_path(1,3).

Don’t nest routes too deeply! If you’re more than a layer or two deep, something should be different. In fact, oftentimes you’ll see only some of the controller actions nested — only the ones that actually need the parent’s ID to uniquely specify it. For instance, you can grab a specific Lesson by knowing only its ID. But to get all the lessons that are listed beneath a specific Course, you need the Course ID so it will have to be nested. Same is true for creating lessons, since they will need a parent specified:

    # config/routes.rb
    TestApp::Application.routes.draw do
      resources :courses do
        resources :lessons, :only => [:index, :create]
      end
    end

If this seems a bit confusing at first, you’ll pick it up quickly when you actually run into it in your own coding. If you find yourself working inside your controller and needing the parent’s ID, the route should have been nested. If you find that you don’t need the parent’s ID, it doesn’t need to be nested. Easy enough.

Member and Collection Routes

Sometimes you want to add another non-RESTful route to a resource. If you’d like to add a route to just a single member of that resource, use the #member method:

    # config/routes.rb
    TestApp::Application.routes.draw do
      resources :courses do
        member do
          get "preview"   # Preview a single course
        end
      end
    end

That route would map to the courses#preview action. You can add as many as you’d like.

If you’d like to add a non-RESTful route to the whole collection of your resource (so you don’t need to specify the :id attribute, like with the index action), you instead use the #collection method:

    # config/routes.rb
    TestApp::Application.routes.draw do
      resources :courses do
        member do
          get "preview"  # Preview a single course (requires ID)
        end
        collection do
          get "upcoming"  # Show a list of *all* upcoming courses (no ID needed)
        end
      end
    end

The upcoming route will map to the courses#upcoming action but will not take an :id parameter.

If any of this seems confusing, just play around with them and run $ rake routes to see what is happening behind the scenes.

Redirects and Wildcard Routes

You might want to provide a URL out of convenience for your user but map it directly to another one you’re already using. Use a redirect:

    # config/routes.rb
    TestApp::Application.routes.draw do
      get 'courses/:course_name' => redirect('/courses/%{course_name}/lessons'), :as => "course"
    end

Well, that got interesting fast. The basic principle here is to just use the #redirect method to send one route to another route. If your route is quite simple, it’s a really straightforward method. But if you want to also send the original parameters, you need to do a bit of gymnastics by capturing the parameter inside %{here}. Note the single quotes around everything.

In the example above, we’ve also renamed the route for convenience by using an alias with the :as parameter. This lets us use that name in methods like the #_path helpers. Again, test out your $ rake routes with questions.

Advanced Layouts: Nesting Layouts and Passing Information

We got pretty good coverage of view layouts in the lesson on Views but one other topic involves rendering multiple layouts for one page, which allows you to create unique sections that still reuse a lot of the stylings that you might want to keep consistent across your whole site (e.g. the footer). For example, maybe the user pages should have a different styling than your home page. The first thought might be to try and have a different stylesheet for each layout but remember that Rails’ Asset Pipeline jams all your stylesheets together anyway.

A better way of doing things is to tell your layout to do some stuff (whatever you might normally have your layout do) and then render another layout using the render :template => "your_layout.html.erb" method. You are sort of using your layouts like a view might use a view partial.

You can also pass information from the first layout to the one it renders by using the #content_for method. This lets you create logic in your main layout that is dependent on what is passed by your individual layout files… the possibilities are endless.

For instance, you might have a specific layout file for your static pages called app/views/layouts/static_pages.html.erb. This file will be rendered by default (if it exists) for views generated from your StaticPagesController (which is a Rails default). Let’s say, though, that you want your static pages to look almost identical to the rest of the site but you don’t want the navbar to appear across the top.

In this case, you would tell your static_pages.html.erb layout to call the application.html.erb layout but also pass it some special CSS by using the #content_for method, e.g.

    # app/views/layouts/static_pages.html.erb
    <% content_for :stylesheets do %>
      #navbar {display: none}
    <% end %>
    <%= render :template => "layouts/application" %>

Then your application.html.erb layout needs to be set up to catch that content and use it, for instance by adding this #yield line:

    # app/views/layouts/application.html.erb
    ...
    <head>
      ...
      <style><%= yield :stylesheets %></style>
    </head>
    ...
    render :template => "static_pages.html.erb"
    ...

When you #yield to a particular content block, in this case :stylesheets, it will essentially drop the code from inside of that content_for‘s block to where the #yield method was. So in the above example, we effectively added some CSS styling to the application layout by first rendering a special static_pages.html.erb layout and then passing the styles to the main application.html.erb layout using #content_for. The result would look like:

    # app/views/layouts/application.html.erb
    ...
    <head>
      ...
      <style> #navbar {display: none} </style>
    </head>
    ...

This trick is useful for more than just passing stylesheet information… any time you find yourself wanting to make a section of your site look different but without totally redesigning it with a fully new layout, you might consider nesting your layouts and passing information from one to another.

Metaprogramming Rails

What is “Metaprogramming”? It’s a great and useful concept that’s used all over Rails and you can put it to work yourself too. It’s basically the idea that your application or script actually creates functions or methods or classes on the fly while it’s running and can dynamically call them as well. It’s one of the great parts of using an interpreted language like Ruby… it’s sort of baked into the language. We’ll just skim the surface here but you should definitely look into it more on your own once you feel comfortable with the nuts and bolts of Rails.

An example of metaprogramming in action in Rails is with the route helpers. When your Rails application fires up for the first time, it loads the config/routes.rb file, which might contain the line get "home" => "static_pages#home" so your users can type http://www.yoursite.com/home to get back to the home page. Rails then creates a couple method for you, including the home_path and home_url helpers. That’s one part of metaprogramming!

The routes example almost isn’t fair, though, because you wrote your routes.rb file and probably hard coded a bunch of #home_path or #home_url method calls based on what you knew would be in there. What about more dynamic situations where you don’t know ahead of time what the method is going to be called?

Ruby provides the #send method to save the day. If you want to run a method on an object, just send that object the method and any arguments you want. A simple example you can do on your command line is 1+2:

  > 1 + 2
  => 3
  > 1.send(:+, 2) 
  => 3

In an ordinary situation, there’s no reason to use the #send method but if you don’t know which method you’re going to need to call, it’s a lifesaver. Just pass it the symbolized name of the method you want to run on that object and Ruby will go looking for it.

But how do you define a new method on the fly anyway? In this case, you can use the #define_method method, which takes the symbol of what you’d like to define and a block representing the method itself. The following examples were taken from this metaprogramming guide from ruby-metaprogramming.rubylearning.com:

    class Rubyist
      define_method :hello do |my_arg|
        my_arg
      end
    end
    obj = Rubyist.new
    puts(obj.hello('Matz')) # => Matz

Another very powerful tool is the #method_missing method. You’ve certainly seen errors that say something to the effect of “Hey you, you tried to call a method that doesn’t exist!” and the stack trace will probably run through something called method_missing. Most likely, you had a typo and spelled your method incorrectly.

Basically, #method_missing is a method of Ruby’s BasicObject class which gets inherited by every single object in Ruby and it is called whenever you try to run a method that doesn’t actually exist. It also gets passed all the arguments you tried to send and any blocks that went with it. That means that you can override #method_missing yourself for a given object and use whatever was previously called, for example printing out a message saying the name of the method you tried to call and its arguments:

    class Rubyist
      def method_missing(m, *args, &block)
        str = "Called #{m} with #{args.inspect}"
        if block_given?
          puts str + " and also a block: #{block}"
        else
          puts str
        end
      end
    end
  > Rubyist.new.anything
  Called anything with []
  => nil

  > Rubyist.new.anything(3, 4) { "something" }
  Called anything with [3, 4] and also a block: #<Proc:0x007fa0261d2ae0@(irb):38>
  => nil

Metaprogramming is really nifty stuff and there are tons of interesting uses for it. You don’t need to master it to learn Rails, so only dive into it once you’re comfortable with Rails, but it will certainly be useful to you in the real world. There are all kinds of metaprogramming tricks and patterns and tips out there but it’s beyond the scope of this course to dive into them.

Here’s a good example of simple metaprogramming to DRY up your code.

Check out Metaprogramming Ruby by Paolo Perrotta if you’re really curious.

Design Patterns

Design patterns have a mixed reputation among software developers. On the one hand, they represent “best practices” for how to code past a given situation (not specific code, just a template for how to fix something). On the other, they can be sort of needlessly prescriptive. See the Wikipedia article on Design Patterns for an overview. We won’t be covering specific patterns in this course.

The Wikipedia article on SOLID provides a good overview and good links related to SOLID software design. If you’re looking to write great code, you’ll need to know each of the principles the letters represent (paraphrasing):

Luckily, Rails has done a pretty good job of following these, so you should have absorbed some good habits just through using it. But you’ll want to take a minute and read up on each of them (including the odd-sounding ones) because they’re fairly central to all software engineering (and a ripe interview question).

If you’re particularly interested in pursuing design patterns, check out the “Gang of Four” (GoF) Patterns laid out in this blog post from blackwasp.co.uk.

There’s a useful book written on anti-patterns, which can help you clean up your code by identifying bad smells, called Rails Antipatterns by Tammer Saleh and Chad Pytel.

I18n: Internationalization

Internationalization and Localization is the process of adapting your application to fit specific geographies and/or languages. It’s outside our scope to cover, but for those who are interested, check out this Sitepoint tutorial on it, as suggested by K. Bates.

Your Assignment

  1. Skim the Rails Guide on Routing section 2.6 about namespacing.
  2. Read the same guide sections 2.7-3.7 to learn about nested, member and collection routes and more.
  3. Read the same guide, sections 3.8-3.15 for a variety of different advanced routing topics including constraining the inputs to your routes and redirection.
  4. Skim the same guide, chapter 4. Some stuff we’ve seen but most is just to give you a sense for what’s possible. When you need it, you’ll probably Google your way back there.
  5. Read the Rails Guide on Layouts section 3.5 to see how to pass information between your view file and your layout file, including CSS styles. Really take a minute to understand what’s going on in the example there.
  6. If you’re interested in peeking at metaprogramming, read through http://ruby-metaprogramming.rubylearning.com/. It’s not essential to building early Rails apps but you’ll definitely start running into it more in “the wild”.
  7. Glance through this Slideshare Presentation on SOLID principles.

Conclusion

In this lesson we covered some fairly random and intricate concepts but useful stuff to at least get familiar with, even if you’re not going to use it every day. Experience is the real key here — in the course of building awesome stuff you’ll run into the need for all of the things you just learned and it might just save you a lot of time and complexity in your code.

The more general principles like SOLID design and metaprogramming will be useful to you regardless of whether you stick with Ruby and Rails or move on to better and brighter things.

With all that completed, there’s not much else to go… it’s time to get started on your final project!

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something

 


Project:

Final Project

There’s a pretty popular social networking app you should build. They may have made a movie about it.

Project: Ruby on Rails Final Project!!!

Don’t forget to use Git to save your projects!

Project: Building Facebook

You’ve come a long way, congratulations! At this point, you should feel comfortable with building new Rails applications, modeling data, and working with forms. This project will require you to put all your newfound knowledge to the test. It should serve as a great portfolio piece for what you’re capable of. It’ll take some thought and time but it’s certainly within reach of your skills.

You’ll be building Facebook. As usual, any additional styling will be up to you but the really important stuff is to get the data and back end working properly. You’ll put together some of the core features of the platform — users, profiles, “friending”, posts, news feed, and “liking”. You’ll also implement sign-in with the real Facebook by using Omniauth and Devise.

Some features of Facebook we haven’t yet been exposed to — for instance chat, realtime updates of the newsfeed, and realtime notifications. You won’t be responsible for creating those unless you’d like to jump ahead and give it a shot.

Your Task

Build Facebook! You’ll build a large portion of the core Facebook user functionality in this project. We won’t be worrying about the Javascript-heavy front end stuff but you won’t need it to get a nice user experience.

You should write at least a basic set of integration tests which let you know if each page is loading properly and unit tests to make sure your associations have been properly set up (e.g. testing that User.first.posts works properly). Run them continuously in the background with Guard (See the Ruby on Rails Tutorial Chapter 3.6.2).

This project will give you a chance to take a relatively high level set of requirements and turn it into a functioning website. You’ll need to read through the documentation on Github for some of the gems you’ll be using.

Keep the following requirements in mind. We’ll cover specific steps to get started below this list:

  1. Use Postgresql for your database from the beginning (not sqlite3), that way your deployment to Heroku will go much more smoothly. See the Heroku Docs for setup info.
  2. Users must sign in to see anything except the sign in page.
  3. User sign-in should use the Devise gem. Devise gives you all sorts of helpful methods so you no longer have to write your own user passwords, sessions, and #current_user methods. See the Railscast (which uses Rails 3) for a step-by-step introduction. The docs will be fully current.
  4. Users can send Friend Requests to other Users
  5. A User must accept the Friend Request to become friends
  6. The Friend Request shows up in the notifications section of a User’s navbar.
  7. Users can create Posts (text only to start)
  8. Users can Like Posts
  9. Users can Comment on Posts
  10. Posts should always display with the post content, author, comments and likes.
  11. Treat the Posts Index page like the real Facebook’s “Timeline” feature — show all the recent posts from the current user and users she is friends with.
  12. Users can create a Profile with a Photo (just start by using the Gravatar image like you did in the Rails Tutorial)
  13. The User Show page contains their Profile information, photo, and Posts.
  14. The Users Index page lists all users and buttons for sending Friend Requests to those who are not already friends or who don’t already have a pending request.
  15. Sign in should use Omniauth to allow a user to sign in with their real Facebook account. See the RailsCast on FB authentication with Devise for a step-by-step look at how it works.
  16. Set up a mailer to send a welcome email when a new user signs up. Use the letter_opener gem (see docs here) to test it in development mode.
  17. Deploy your App to Heroku.
  18. Set up the SendGrid add-on and start sending real emails. It’s free for low usage tiers.

Extra Credit:

  1. Make posts also allow images (either just via a URL or, more complicated, by uploading one).
  2. Use the Paperclip gem to allow users to upload a photo to their profile.
  3. Make your post able to be either a text OR a photo by using a polymorphic association (so users can still like or comment on it while being none-the-wiser).
  4. Style it up nicely! We’ll dive into HTML/CSS in the next course

Getting Started

  1. Think through the data architecture required to make this work. There are a lot of models and a lot of associations, so take the time to plan out your approach.
  2. Build the new postgresql rails app $ rails new odin-facebook --database=postgresql, initialize the Git repo, and update the README to link back to this page.
  3. Work your way down the list above! Each step will involve a new challenge but you’ve got the tools.
  4. You can populate data like users and posts using the Faker gem, which is basically just a library of sample names and emails. It may just be easier, though, for you to write your own seeds in the db/seeds.rb file, which gets run if you type $ rake db:seed.

Student Solutions

Send us your solution so we can show others! Submit a link to the Github repo with your files in it here using any of the methods listed on the contributing page. Please include your partner’s github handle somewhere in the description if they would like attribution.

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something


 

Step 5:

Conclusion

Holy cow, you’ve gotten to the end of the road! …Sort of.

Conclusion and Next Steps

You’ve reached the end of the scope of this course and should feel pretty good about your Rails skills. That doesn’t mean you should feel like you understand everything, but you should be able to build a Rails application with the kind of functionality which is actually useful in the real world. It probably won’t look too pretty, but that will come in the next few courses.

This isn’t the last course in the curriculum and you’ve got quite a way to go before hitting that “full stack” point, but it’s as far as we’ll get with Rails and it’s pretty darn far. Despite how far you’ve come, it’s up to you to keep building stuff, asking questions, and digging deeper into both Rails and best practices of software engineering in general.

At this point, you’ve got the Rails building blocks but the learning is never finished. Your first six months on the job as a Rails dev will involve learning at least as much information as you just did. The point of this course has been to get you to a place where you can start thinking about actually getting that first job.

Next Steps

This final lesson isn’t designed to explicitly teach new material, just point you in the right direction if you’d like to dig a bit deeper before moving on. Or maybe you’ll bookmark it and come back when you want to see where to head next in your Rails journey.

Rails is deep… there’s a lot going on behind the scenes and it will take a long time to actually understand how it all works and the best ways to use it. The best way to figure it out is to work for a company that uses it and get paid to learn. If that’s not an option, building your own stuff and reading on your own time can be a good substitute. There’s new information being created every day in blog posts, Stack Overflow posts, and podcasts.

A good first step is to reread the Rails Guides. There are some sections we skipped and some guides we never got to (especially in the “digging deeper” section). In particular, the following sections might be interesting:

Security

If you start working on more public-facing applications, security will become more important. Check out the Rails Guide on Security for more information.

Rake Tasks

Rake tasks are a special way of running scripts that can use your application. You’re already familiar with some like $ rake db:migrate, but you can also create your own. This website uses a Rake task to populate the curriculum from its Github repo. Check out the Rails Guide on Command Line and Rake Tasks for more information.

Caching

Caching makes your application faster by reducing database calls. Check out the Rails Guide on Caching to learn more.

Books

Here are a few books that will take you a bit deeper as well:

Other Resources

  • RailsCasts by Ryan Bates are incredibly valuable. Great ways to actually see the implementation of various gems or practices.
  • GoRails alternative to RailsCasts.
  • The RailsApps Project provides lots of great tutorials that walk you through building real-life scenarios like integrating Devise and CanCan with your app or building a payments backend.
  • RubyFlow community blog will have some interesting stuff pop up from time to time.

Contributing

You know more than you think. Remember when we just said that you should keep building stuff? This website is completely open source and needs your help to improve. We have a dedicated group of current and former students who help add features and proofread the curriculum. The best part is that it’s completely public and free so you can watch or participate at whatever level you’re comfortable.

It’s a great way to start learning about agile development methodologies and to start doing meaningful development work in a friendly and supportive environment. So check out our Google Community and our Meetup Group to see what we’re up to. We’d love to have you get involved!

Conclusion

I want to emphasize again that the learning never really stops but also that you’ve come a long way. Stick around for the next few courses and you’ll take a good core and build some very interesting things. In the HTML/CSS course, you’ll learn to make your Rails applications look like actual websites instead of text dumps. In the Javascript course, you’ll learn how to take everyday web apps and make them much faster and more dynamic in the browser.

So there’s a lot left to go but it gets better and better. Stick with it!

Additional Resources

This section contains helpful links to other content. It isn’t required, so consider it supplemental for if you need to dive deeper into something