-
Notifications
You must be signed in to change notification settings - Fork 6
Home
The README.md
file contains instructions on how to create your own copy of this project.
-
rake -T
Print out all available rake tasks w/ a small description of each.
-
rake routes
Print out Rails' current "routing table" as defined by
routes.rb
-
rake spec
Run all the automated RSpec tests for this project (aka "the test suite").
-
rake db:setup
Run this on a fresh Rails application to set up the databases. Note:
database.yml
must be configured correctly. -
rake db:migrate
Run all outstanding database migrations, ensuring your database schema is up to date. You'll need to run this every time you create a new migration or pull down code that includes a new migration.
This project is structured as a sequence of iterations, each of which builds on previous iterations. We do not expect students to complete each and every iteration. Rather, they serve three important roles:
- Models for good engineering and product management, i.e., what do we build, in what order, and why?
- Natural checkpoints to ask for a code review or other feedback
- The ability to accommodate students with different interests, skill levels, and time constraints.
Note: This version is already built. It's what you'll get when you clone the repository! v0.2 is the first version for you to build.
In this version
- A user may create a
Link
by submitting a destination URL to the site - A user may see a list of all
Links
submitted to the site - Every
Link
has an auto-generated short URL, which a user may visit to be redirected to the original destination URL.
In short, it's like the bare minimum functionality of bit.ly
.
In this version, we'll add basic click tracking so that we know how many people have clicked on each of our links. To do this:
-
Add a new integer field to the
links
table calledclicks_count
with a default value of0
and ensure it can't have aNULL
value. Do this by running$ rails generate migration AddClickCountToLinks clicks_count:integer
Edit the migration file to set the default to
0
and disallowNULL
values.See the ActiveRecord Migrations documentation for information on how to do add a new field to an existing database table. You'll want to use
rails generate migration
to create the appropriate migration, which itself should contain a call toadd_column
. Hint: Search for these keywords in the documentation.Remember, run
$ bundle exec rake db:migrate
to run a migration after you've created it.
-
Add the appropriate validations to the
Link
model. -
Create a new instance method called
Link#clicked!
on theLink
model which increments the value ofclicks_count
. -
Call
Link#clicked!
in theLinksController#show
action. -
Show the
clicks_count
for each link on the homepage. -
Add appropriate model tests to
spec/models/link.rb
so that we knowLink#clicked!
is doing what we expect. -
Add appropriate controller tests to
spec/controllers/links_controller_spec.rb
so that we know the controller is incrementing the click count.
Add support for user authentication and user accounts using ActiveRecord's has_secure_password feature. Please don't use something "off the shelf" like devise. Right now, it's important we get a clear picture of all the major moving parts involved in "user authentication."
Note: Please read the has_secure_password
documentation carefully. It describes what fields you need to add to your users
table. It also contains a sample of very helpful code snippets around user authentication.
This feature requires that...
- A
User
can register for the site using their email and password - A
User
can log in to the site using their email and password - A
User
can see the list ofLinks
they submitted while logged in.
People should still be able to submit links without an account, though.
To create the User
model, run
$ rails generate model User email:string:uniq password_digest:string
To add the user_id
field on the links
table, run
$ rails generate migration AddUserToLinks user:references
Again, remember to run bundle exec rake db:migrate
to actually apply these migrations.
Do your best to create tests for the User
model and any controllers you create. You'll likely be creating two controllers for this iteration: UsersController
for creating new user-related actions and SessionsController
for logging in and logging out.
Don't worry if you struggle to write tests around user authentication. Do your best and ask for feedback.
Now that we have support for user authentication, it makes sense to allow links to be updated or deleted.
- As a
User
, I want to be able to edit theLinks
I submit. - As a
User
, I want to be able to delete theLinks
I submit.
Make sure a User
can only delete or edit links they've submitted and not anyone else's. Do your best to write tests for these situations.
Note: You'll need to add new methods to the LinksController
and add lines to routes.rb
to tell Rails how to map URLs to those new methods.
Tip: At this point, you may or may not know what Rails expects. The easiest way to find out? Create a dummy project elsewhere containing a scaffolded-out Link
model. You'll be able to look around this dummy project and see how Rails likes to organize things by default.
To create the dummy project, go to a new directory (outside your url-shortener
project directory) and run
$ rails new dummy-project
Inside that the dummy project's root directory, run
$ rails generate scaffold Link short_name:string url:string
This will create a "fresh" Rails application with a fully-scaffolded Link
model, controller, and views. You should use this as a reference for what the Rails conventions are.
Sometimes, we won't want the world to know we love sharing links to cute animals. Let's enable some privacy. As a User
, I want the option of marking the Links
I submit as "private", so that they aren't listed on the homepage.
Here's the migration command:
$ rails generate migration AddPrivateToLinks private:boolean
Make sure you go into the newly-created migration file to set a default value for the field and disallow NULL values. Again, remember to run
$ bundle exec rake db:migrate
to actually apply the migration.
Right now, we're only counting the raw number of clicks on each link. If you've ever used bit.ly, though, you know it tracks much more: referrer information, geographical information, when the clicks occurred, and so on. Let's add support for this while maintaining backwards compatibility with our pre-existing click_count
interface.
On the database and model side, you'll need to do two things:
- Remove the
clicks_counts
column from thelinks
table. - Add a new table called
link_clicks
which will have one row per click containing whatever information we want to record.
Remove the clicks_counts
column from the links
table by creating a new migration as follows:
$ rails generate migration RemoveClickCountFromLinks clicks_count:integer
Create the LinkClick
model and migration by running
$ rails generate model LinkClick link:reference referrer:string
Change the Link
model as follows
class Link < ActiveRecord::Base
# We want to write link.clicks and not link.link_clicks
has_many :clicks, class_name: 'LinkClick'
# ... code ...
# e.g., link.clicked!(:referrer => request.referrer)
def clicked!(click_attributes = {})
self.clicks.create(click_attributes)
end
# Determine number of clicks by size of clicks association
# vs. field directly in links table
def clicks_count
self.clicks.count
end
end
We have a pretty sweet URL shortener at this point. You decide what you want to do to take it over the finish line. Here are some ideas:
-
Improve the user interface. We highly recommend Shay Howe's Learn to Code HTML & CSS.
-
Add cross-
Link
tracking. Two users can add the same URL, but they're tracked separately. Modify the application so that if multiple users enter the same URL they all get distinct short URLs, but the application can answer questions like "How many redirects have we done to a specific URL?" and "How many times has a specific URL been shortened?"This will require a new table because a "long URL" and "short URL" are now in a 1-to-many relationship instead of a 1-to-1 relationship. That is, a "long URL" can have many "short URLs".
-
Now that we have better tracking, add better reporting. Find a way to graph clicks over the last day, week, and month. What domains are the most common sources of traffic for a given link? Note: To make interesting graphs, you might want to insert lots of fake data into your database. The faker gem makes this very easy and it's already included in the
Gemfile
.