Project Ramon

A learning journey from a Ruby noob perspective

Sevendaysports Lessons Learned

sdasports_complete_header_image

I am finished with my current sevendaysports project and wanted to write a quick post moderately-sized post about all of the lessons I’ve learned during my time building this project using AirPair.

Data-Modeling

I was introduced to quite a few powerful new concepts in this arena. I learned how to use two foreign keys in one parent model. In sevendaysports, I have an Event class that establishes a game between two teams. I was able to associate an event to Team and add two Team objects by doing the following:

There is an explanation in the Rails API that you can find by typing in belongs_to in the search bar at the Rails API site. With my project, since I wanted to add two Team instances I just called one team :home_team and the other team :away_team and passed each one-to-one association the class_name: "ClassName" argument.

Another great thing I learned was the purpose of class methods, and how to use scopes. Edward Anderson was very instrumental in helping me understand how to set up and even chain a scope, and in understanding how I could use a scope or class method for benefit in my application.

Here is a sample of some scopes Edward and I created during a pair.

The above scopes will pull event records out of the database, you can gain a sense for what a particular scope is pulling by the scope’s name. For instance :by_user, :by_home_team, and :by_away_team are pulling events tied to a specific object id A user_id, home_team_id, or away_team_id and returning results. For the :by_user scope its ordering all events by a user’s name, and for :by_home_team and :by_away_team are pulling all events by a home_team_id or away_team_id respectively.

One more thing Edward shared with me during this project is the Rails style guide by: Bozhidar Batsov.

I really love this repository, as it takes a lot of style guesswork out of writing when attempting to keep your code readable. I signed up to the list for a little while to get a sense of what went on and found that the discussion of rails styling conventions were in depth enough so that I can learn a lot about why decisions were made as well as what the consensus happens to be.

Here is an illustrations of how my models are set up:

Since scopes are a Rails shortcut for class methods, I have placed them under my association declarations and above my instance methods. Also noticed how the last two scopes from the illustration above are just to order how events are returned. So I can use :order_desc or :order_asc with the other scopes and receive further parameters like so.

HTTP Request/Response cycle

The HTTP request/response cycle in an MVC framework such as Rails is handled by Controllers. This was an area where I was sorely lacking in some fundamental understanding of how a client request is handled and then served.

Here are a couple of past posts on this topic:

I also learned to understand filters, and parameters a lot better.

A filter are methods that are ran before, after, or around a controller action. They are also inheritable methods, so if we set a filter in our ApplicationController, the set filter will be run on every controller in our project.

Parameters in Rails allow us to access client data in our controllers. The two kinds of parameters available in a web application are query string parameters and POST parameters. A query string parameter would be anything after the ? in the URL, and post parameters typically come from an HTML form filled in and submitted by the client. Both of these parameter types are available in the Rails params hash in our controllers since Rails doesn’t make any distinction between the two.

Here’s a view of the sevendaysports’ universities_controller to demonstrate both filters and params.

The before_filter :get_university, except: [:index, :new, :create] on line two above will call the private method on line: 42 in the above example. The filter evaluates get_university for every action in our controller except for the ones that were set aside for ommision, :index, :new and :create.

You can also do an inverse of the except hash with only. If we were to write our before_filter using only we could achieve the same results as our except filter does by writing the following.

This achieves the same result as our except hash. The filter evaluates the get_university private method only for the :show, :edit, :update and :destroy action methods. I was taught that its probably best to use whichever filter leaves us with having to type less.

To demonstrate parameters in action, we can have a look at what happens in the new and create actions.

When a user selects the ‘create a university’ button, a GET verb is sent to the application’s server and locates the views and form_fields that match our Object’s attributes and then serves them back to the client via the browser. The parameters are then entered by the user (in the form fields), and the user selects the ‘submit’ button. The submit button sends a POST response and Rails will route to our create action. Once there the parameters that the user submitted and some additional parameters such as a character encoding check and an authenticity_token for security will be inserted into the appropriate database columns. Once this is done then the record is saved or committed.

Here are a couple of images to illustrate:

sdasports_complete_img1

This is the server output for GET “/universities/new” which renders the new & _form templates along with the rest of the site templates.

sdasports_complete_img2

And this is the server output for POST “/universities” which captures all of the user entered data, along with some additional encoding and security data, inside of a hash named Parameters and then redirects to the specific university’s resource page which is shown as Redrected to http://localhost:3000/universities/3. Then issues a completed 302 which is an HTTP standard response for a successful redirect.

Assets and the Front End

Rails has a powerful asset pipeline that will take all of our .css and .js files and condense them into one master .css and .js file. We can add additional asset files to be included for either .css or .js by adding directives to our CSS and javascript manifest files.

A quick example of what a manifest file looks like could be:

Application.css is for including our CSS directives.
sdasports_complete_img3

And Application.js is for including our JS directives.
sdasports_complete_img4

It is Rails convention to add 3rd party asset files (an example would be the addition a website template’s files that we want to keep separate from our code) via the vendor/assets folder. We could then create a require file_name directive to add to either or both manifest file. Doing so would allow Rails’ asset pipeline to include these third party files in its pre-compililation into master .css and .js files respectively.

Gleb Mazovetskiy gave me some great guidance on how to utilize Bower to manage my front-end dependencies. You can check out my post on that topic here.

Although I’ve missed two deadlines for this project, I have found immense value from all of the guidance I’ve received. I’m no-doubt a better developer noob than before I started with AirPair and the mentors and friends I’ve made along the way. I look forward to sharing my next project with you all after taking a few weeks to nail down Ruby and Rails knowledge.

Stay tuned..

Advertisements

Categories: AirPair, Newbie, Ruby on rails

Tags: , , ,

5 replies

  1. Note about scopes (if you don’t mind!)

    You don’t need to use lambdas for ALL scope declarations; the simple rule: lambdas are necessary if the scope must be evaluated in runtime (so for example when it contains things that are time-related or if scope accepts a parameter). In other cases you can use AR methods directly:

    scope :order_desc, order(‘event_on DESC’).limit(3)
    scope :order_asc, order(‘event_on ASC’)

    or similarly

    scope :visible, where(active: true)
    scope :last_visible, visible.order_desc # scope which builds on other scopes

    I would also suggest using a slightly different naming, instead of:

    scope :order_desc, order(‘event_on DESC’).limit(3)

    why not use:

    scope :latest, order(‘event_on DESC’).limit(3)

    to reflect what it really means.

  2. Not at all Marek, I highly value your input!
    Thank you for the insight into when to use Lambdas for scopes and using descriptive names for my scopes based on the meaning of the query it performs.

  3. Awesome 🙂 So I’m not sure if you know / came across this as well, it’s a bit scope-related, but more related to the lazy evaluation of the ‘where’, ‘order’ etc:

    assuming you have some dynamic logic in the code, you might use dynamic condition building by chaining conditions in the calling code (preferably at the model / non-controller level):

    @events = Event.visible # events are not fetched yet
    @events = @events.latest if some_condition1 # events are not fetched yet
    @events = @events.for_user(@current_user) if some_condition2 # events still not fetched yet

    as soon as you start iterating over @events (or try outputting them – like in IRB console), then ActiveRecord will go to the database.

    It makes it non-obvious when in IRB console, because each statement you evaluate there is ‘inspect-ed’ by the console. So if you say in IRB:

    events = Event.visible

    you will actuall make the query; but that’s only because you’re printing the result

    But if you do:

    events = Event.visible; 1

    then ‘1’ gets printed, and the ‘events’ now stores this lazy-evaluated condition (and no SQL executed at this point)

  4. Ok, sounds good. I’ll keep this in mind in the future!

Trackbacks

  1. AirPair.com – What I’ve Learned pt. 2 | Project Ramon

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s