Hello from after Mod2 project submission!
We just finished our first project within Mod2. As referred to previously, it was the Bike-Share project where we were tasked to develop a web application that utilized a database populated from San Francisco’s bike share service data with stations, trips and weather details and provuded access to content of the base. However access to the databse content wasn’t only through standard routes index
, new
, show
, edit
, our implementation also included a dashboard functionality.
It’s been quite an effort and in the process leading up to our project review on Thursday, I learnt a ton! Looking back: it is just simply amazing how much one can learn in a single week. Wow. This alone makes me very excited just thinking about what I can still learn here at Turing
Since again I’ve learnt a lot and just as after previous projects I feel I am that much smarter again, I thought I would share here something that just cliked during this project and what I really think is a cool feature.
Our project relied very heavily on large data sets, which were stored in various tables within our database. In order to get the necessary data out of our database, we had to set up the necessary associations in our models, so that we could utilized the necessary ActiveRecord quiries. That is when I learnt about Association Extension
. If you rather explore it and read it for yourself, simply go to the ActiveRecord::Associations::ClassMethods documentation
For reference, this is how our data was structured within our database (used SQL demo from Ondras Zarovi’s site):
Let’s go through my favorite part here using our stations
and trips
tables. In this case, each trip
had a start_station_id
(unique id
of the station where the trip started) and an end_station_id
(unique id
of the station where the trip ended).
We set up the has_many
association in our station
model to be able to find all trips which started at a particular station through start_trips
and to find all trips which ended at a particular station through end_trips
.
class Station < ActiveRecord::Base
has_many :start_trips,
class_name: "Trip",
foreign_key: "start_station_id"
has_many :end_trips,
class_name: "Trip",
foreign_key: "end_station_id"
end
Before diving in deeper, a simple example as to how association extension
differs from class methods
and instance methods
.
From coding point of view here is a list where setting up the association extension
differs from class methods
and instance methods
:
1. Definition: within a do...end
block attached to the association definition (see example below)
2. Calling: append to the association call, just like any other ActiveRecord methods you would use
3. Reference: since this extension is within a block that belongs to an association, using output of that association is readily avaialble for the extension method, no need to call it (ee code example later in this post)
class Station < ActiveRecord::Base
has_many :start_trips,
class_name: "Trip",
foreign_key: "start_station_id" do
def say_hello
"Hello from the association block!"
end
end
def say_hello
"Hello from the model!"
end
end
How would we call these methods? Since our stations
and trips
tables are already populated with data, for simplicity here, I use Station.first
as our station object
to call our methods on.
So far not much value add moving say_hello
and make it an association extension
. Let’s take a look at an actual feature request that we had to implement so we can see how different the code would be in that case.
For this next example, I picked a feature to look up the date when the most trips started at any given station.
class Station < ActiveRecord::Base
has_many :start_trips,
class_name: "Trip",
foreign_key: "start_station_id" do
def date_of_highest_count
group(:start_date).order("count_start_date DESC").count(:start_date).first.first.to_s
end
end
def date_of_highest_count_of_trips_started
start_trips.group(:start_date).order("count_start_date DESC").count(:start_date).first.first.to_s
end
end
Then once more let’s jump over to our Tux console to see what this implementation offers:
Though both the date_of_highest_count
and date_of_highest_count_of_trips_started
methods deliver the same results, but at this point I prefer the association extension implementation for the following reasons:
1. Don’t need to call start_trips
when I write the code for the date_of_highest_count
method
2. Better separation of functionality: by appending date_of_highest_count
to start_trips
I know that by calling date_of_highest_count
, my search for the date is within the list of trips started at this station.
What do you think? What is your preferred way of implementation?