Starting learning to code with Team Treehouse

So, contrary to what I said in my previous blog post about what my next steps would be, I decided to move on to Team Treehouse (they sent me an email for a free month).  Team Treehouse is similar to sites like Codecademy and Code School in that it’s interactive.  However, unlike Codecademy, it uses video lessons to teach and then uses quizzes to reinforce the knowledge.

I decided to do the “Become a Web Developer” Learning Adventure, which covers everything from HTML/CSS to Git, Ruby, jQuery, JavaScript, CoffeeScript and relational databases.  So far I’ve completed the first section which was “Build a Simple Website”.  In this, I got a refresher on HTML, and ended up making a one page website for a cupcake shop using CSS.  It gave me a good primer on grids which is something I haven’t really worked with before.  Content-wise though, I found it to be a very basic level course that took me about an hour.  I skipped many of the videos and jumped to the quizzes because I’ve done enough HTML in my life to squeak by.  Sublime Text helps me with any syntax I’m not 100% rock solid on.

One thing I really like about Team Treehouse is the videos.  The instructional videos are surprisingly high quality and high budget.  They use onscreen writing of code along with little diagrams or other visual displays to walk through important concepts.  The learning is concise, professional, and so far bug-free.  The text editor for the quizzes is slightly slow, and I don’t feel that the course actually tests you on ALL of the content so I’m not sure how good the absorption will be when I am learning something brand new to me.

You can see my profile here.  It has all the standard gamification elements like badges.  It also has an overarching video adventure that unveils a story as you progress through the courses, which I’m assuming encourages retention from all the people with good intentions who don’t stick with a program.

I’ll update as I go throughout the program.  If you want to sign up, click this referral link so that I get a free subscription. =)

Done with One Month Rails: A Summary

Today I finished up the One Month Rails course in exactly 15 days.  I was basically a Weekend Warrior, in that I didn’t work on this much during the work week.  I think it was a substantial course and worth the $20 that I paid for access to it.

Pros:

+  Getting me setup with an environment, deploying to Git and Heroku was probably the best part about this.  Compared to Codecademy or other such sites, this course actually got me started on the path to making a real app and showing it to the world within the very first lesson.  That is a huge motivator to keep going, and also gave me essential knowledge that I need to start app #2.
+ His teaching was slow and his voice is calming and his delivery is great.  I like how he explained why we’re doing everything.
+ I feel like I have a solid knowledge of searching the web for answers to things and importing gems that might be useful to my project.
+ I got a brief glimpse into Ruby syntax, though I don’t necessarily understand it yet.
+ I have a working app at the end that is basically Pinterest minus the boards that I can show to people.  This is exciting.

Con:

+ I don’t think it taught me how to code, at all.  It taught me the basics of creating an app with Rails and how to edit/modify things.  I feel like I could build any number of apps and I could probably Google for the code snippets required to add just about any functionality.  Do I feel that would make me a “Rails developer”?  No.  I don’t really understand how to write any Ruby code.

I liked this course. It gave me the knowledge that I need to start making another app, once I come up with an idea.

My next steps:

Do the Ruby course at CodeSchool and Codecademy so that I can understand the syntax of that language better.  Read Why’s Poignant Guide to Ruby.  Then, I’ll do Michael Hartl’s Rails tutorial.  After that, I’m going to build something and this will give me time to figure out exactly what. =)

Adding user profiles

Right now we have the ability to edit our own user profiles (our email address, name, and pw) but what if we wanted to be able to click on a user’s name and view a profile page for them?  That’s what we’re doing here.

I don’t need to create a whole new scaffolding for users like I did for pins, because a scaffolding allows us to CRUD (create, read, update, destroy) and we can already create users, delete users, etc.  What we want to do is modify the Devise gem, so if you Google search for “show page Devise” there is a StackOverflow question that helps us do this very thing.

First thing is running:

$ rails generate controller User show

This creates a user controller file automatically  us and the show action is blank as you can see here:

class UsersController < ApplicationController
  def show
  end
end

Then I go into my pins controller and copy the top line of the show action, which is:

@pin = Pin.find(params[:id])

And change pin to user in that code and put it in that empty show action in the Users controller.

Then I open up the Users-> Show view (which was automatically created for us) and replace the contents with this (which doesn’t show up well when pasted in WordPress).  Now we edit our routes file and under devise_for :users we put in

match 'users/:id' => 'users#show', as: :user

Finally in our Pin view we replace part of the code:

 .
  .
  .
        <strong>
            Posted by <%= link_to pin.user.name, pin.user %>
        </strong>
  .
  .
  .

Now clicking on someone’s name on the index page brings up a user profile showing all their pins.

Screen Shot 2013-04-08 at 5.35.41 PM

Adding pagination

Pagination was one of the easiest things to add.  I installed the will_paginate and bootstrap_will_paginate gems.

I edited my Pins controller:

.
.
.
  def index
    @pins = Pin.order("created_at desc").page(params[:page]).per_page(20)
.
.
.

At the bottom of app/views/pins/index.html.erb I added:

<%= will_paginate @pins %>

And now I have good looking pagination!

Screen Shot 2013-04-07 at 9.55.45 PM

 

Creating dummy users with Faker

This is how you add dummy users and image uploads with Faker.  Install the gem by adding it to your gemfile:

gem ‘faker’, ‘1.1.2’

I made a folder called ‘sampleimages’ in my app and put a few different images in it.  Next, I create a new ‘task’ under lib => tasks and call it populate.rake.  I fill it with the following:

namespace :db do
  desc "Fill database with sample data"
  task populate: :environment do
    10.times do |n|
      puts "[DEBUG] creating user #{n+1} of 10"
      name = Faker::Name.name
      email = "user-#{n+1}@example.com"
      password = "password"
      User.create!( name: name,
                    email: email,
                    password: password,
                    password_confirmation: password)
    end

    User.all.each do |user|
      puts "[DEBUG] uploading images for user #{user.id} of #{User.last.id}"
      10.times do |n|
        image = File.open(Dir.glob(File.join(Rails.root, 'sampleimages', '*')).sample)
        description = %w(cool awesome crazy wow adorbs incredible).sample
        user.pins.create!(image: image, description: description)
      end
    end
  end
end

Lastly, I run $ rake db:populate and this makes my site look pretty awesome on development!

Screen Shot 2013-04-07 at 9.40.51 PM

 

 

Image uploading from a URL

Right now my site can only upload images from my computer, but I want to make it upload from URL instead.  So that’s what I’m going to be doing now. 🙂

If I load the schema file in the db folder, I can see that right now I’m storing the following information about my pins:

create_table "pins", :force => true do |t|
t.string "description"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.integer "user_id"
t.string "image_file_name"
t.string "image_content_type"
t.integer "image_file_size"
t.datetime "image_updated_at"

If I want to add image URL in there, I first need to create a migration by doing:

$ rails generate migration AddImageRemoteUrlToPins image_remote_url:string

Now I need to run rake db:migrate to make the database changes.

Now we need to edit the model to tell it what to do if a user wants to upload an image from a remote URL.  I need to  edit the pin.rb model file and make the image_remote_url accessible by adding the following to attr_accessible:

attr_accessible :description, :image, :image_remote_url

Also apparently something with Ruby is that once I define an attribute I can dig into it deeper.  At the bottom of the pin.rb file I add:

	def image_remote_url=(url_value)
 		self.image = URI.parse(url_value) unless url_value.blank?
 		super
 	end

So that was some confusing stuff right there.  Apparently in this case, super means that it’s going to fall back on whatever functionality was in the original method.  self in self.image refers to the pin.

Next we need to edit the _form.erb file so that it’s added to our views so people can try to paste in a URL.  I add this to the file:

<%= f.input :image_remote_url, label: "or enter a URL" %>

Bam, done.

Using Amazon S3

So I noticed that when I accessed my app on Heroku and uploaded images, that if I left them there they would eventually go away and be dead images.  I figured it had something to do with how Heroku doesn’t store images, and I was correct.  Every so often (maybe when the server powers down?) all images and uploads are deleted to prevent people from using Heroku for file storage.  The solution here is Amazon S3, and I’ll use this guide to do it.

I registered for an Amazon Web Services account and waited for it to be activated.  Next I need to paste the following into my production.rb file:

# Configuring Amazon S3 for Paperclip file uploads
config.paperclip_defaults = {
  :storage => :s3,
  :s3_credentials => {
    :bucket => ENV['AWS_BUCKET'],
    :access_key_id => ENV['AWS_ACCESS_KEY_ID'],
    :secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
  }
}

Instead of actually entering in my AWS access keys (which would be really insecure since I’m uploading all of this code to a public repo on Github) I’m going to use those environment variables (ENV) which I set via terminal and don’t have to enter in my code.

After I add that code, I’ll commit and push to Git & Heroku.  Image uploads still don’t work though, because we never set those variables.  That’s okay, I can do that now.  To do this I put the following in Terminal:

$ heroku config:add AWS_BUCKET=your_bucket_name
$ heroku config:add AWS_ACCESS_KEY_ID=your_access_key_id
$ heroku config:add AWS_SECRET_ACCESS_KEY=your_secret_access_key

If I ever want to check on these variables again in the future I can put $ heroku config in the Terminal.  Now, it works!  My images are uploading to S3 and the app is still hosted on Heroku.