2. Agenda – Monday November 26
1. Review of Last Session
2. Rails Controllers
3. Rails Router
4. Rails View and Frontend
5. Followers + Relationships
6. To be Continued… (Interface, Feed)
3. Prework – Setup
• Windows (not recommended if possible):
o http://railsinstaller.org/
o Use Sublime Text for your text editor
• OSX:
o http://railsinstaller.org/
o This includes osx-gcc-installer (200mb)
• Linux:
o http://blog.sudobits.com/2012/05/02/how-to-install-
ruby-on-rails-in-ubuntu-12-04-lts/
5. Review of Last Session
1. The Web and How it Works
2. Ruby Basics
3. Rails Models
4. Authentication and User accounts
6. Ruby – Programmer’s Best Friend
• Ruby is a dynamic, open source
programming language with a focus on
simplicity and productivity. It has an
elegant syntax that is natural to read and
easy to write.
• We will only cover the necessary syntax
needed to create a rails app
• Thankfully, its not a lot
7. Interactive Ruby Shell
• For the following slides, you should follow
along with the Interactive Ruby Shell (irb)
• Open a terminal, type irb and press enter
8. Ruby – Practice
• Tryruby.org (code in ruby on your browser
and work through free exercises)
• Read Section 4.1 to 4.5 of Ruby on Rails
Tutorial by Michael Hartl
9. Rails – Database backed Models
• Store and access massive amounts of data
• Table
o Columns (name, type, modifier)
o Rows
Table:Users
10. SQL
• Structured Query Language
o A way to talk to databases
• Operations (CRUD)
o Create
o Read (Query)
o Update
o Delete
o Schema creation and modification
SELECT *
FROM Book
WHERE price > 100.00
ORDER BY title;
11. Rails – Object Relational Mapping
• Maps database backend to ruby objects
• ActiveRecord (Rail’s Default ORM)
>> userVariable = User.where(name: "Bob")
Generates:
SELECT "users".* FROM "users"
WHERE (name = 'bob')
>> userVariable.name
=> Bob
12. Rails – Object Relational Mapping
>> userVariable = User.where(name: "Bob")
models/user.rb
class User < ActiveRecord::Base
attr_accesor :name, :email
end
• Plural of Model name is table name (User -> users)
• Subclassing from ActiveRecord::Base “Connects” a model to
the database
o Provides CRUD operations on the model
o Database table column names are getters & setters for model attributes
o Model attributes automagically defined from the database table columns
13. Rails – Creating Users - Devise
• We will use the awesome Gem: Devise
• Gems are packages/libraries for your rails project
• Before coding, always see if a gem exists at
The Rails Toolbox
14. Rails - Devise
• Create a new rails app
o rails new MiniTwitter
• Open Gemfile (from last class)
• Add the line:
Gem ‘devise’, ‘2.1.0’
• Run Bundle install from the console
• Install Devise by typing in the console:
rails generate devise:install
• Generate the user by typing in the console:
rails generate devise User
• Run the migration by typing in the console:
Bundle exec rake db:migrate
16. Rails MVC – Quick Review
• Model: methods to get/manipulate data“
/app/models/post.rb
Post.where(...), Post.find(...)
• Controller: get data from Model, make available to View
/app/controllers/posts_controller.rb
def show
@movie = Post.find(params[:id])
end
• View: display data, allow user interaction“
/app/views/users/*.html.erb
– Show details of a Post (description, timestamp, etc)
17. Rails Controllers - Variables
• Some housekeeping knowledge (you’ll see
this a lot in controllers)
foobar # local variable
@foobar # instance variable, starts with @
@@foobar # class variable, starts with @@
$foobar # global variable, starts with $
FOOBAR # Constant, starts with a capital letter
FooBar # Classes are constants
18. Rails Controllers - Intro
• Handles Business Logic
http://localhost:3000/posts/new
class PostsController < ApplicationController
def new
end
end
• Pass Data to Controller via Query String
http://localhost:3000/posts?status=posted
?status=published
?status=published&language=english
19. Rails Controllers - Params
• Params (hash) – get data from url
• Instance variables – pass data to view
http://localhost:3000/posts?status=published
def index
@status = params[:status]
if @status == “published"
@clients = Post.published
else
@clients = Post.removed
end
end
20. Rails Controllers – Params Hash
• Receive Hashes from Forms
o Great for handling data and user input
Form
<form action="/clients" method="post">
<input type="text" name="client[name]" value="Acme" />
<input type="text" name="client[phone]" value="12345" />
<input type="text" name="client[address][postcode]" value="12345" />
</form>
Hash
params[:client] # =>
{name: “Acme”,
phone: “12345”,
address: {postcode: “12345”} <- Notice the nested hash
(corresponding to nested form)
}
21. Rails Controller – Application Flow
• Can redirect to another action/url
http://localhost:3000/posts/new
# send to another action/url
If not_logged_in
redirect_to "/home”
else if not_authorized
redirect_to help_path
else
@post = Post.new
end
• Rails automatically creates
names for url routes (more later)
22. Rails Controller - Rendering
• Passes instance variables and data to view to
render to end user
# Various rendering options
render “some_template"
render layout: "awesome"
render text : "foo"
render json: @post
render xml: @post
render status: forbidden
render file: filename,,content_type: „application/rss‟'
• If don’t call render, Rails will default to view named
action_name.html.erb in the controller’s view path and render it
• Lots of more info here:
http://guides.rubyonrails.org/layouts_and_rendering.html
23. Rails Router – Overview
1. Routes (in routes.rb) map incoming URL s tocontroller
actions and extract any optional parameters!
– Route s “wildcard” parameters (eg:id), plus any stuff after “?” in URL,
are put into params[] hash accessible in controller actions"
2. Controller actions set instance variables, visible to views"
– Subdirs and filenames of views/ match controllers & action names"
3. Controller action eventually renders a view"
app/controllers/movies_controller.rb app/views/movies/show.html.haml
def show <li>
id = params[:id] Rating:
@mv=Movie.find(id) = @mv.rating
config/routes.rb end
GET /movies/:id
{:action=>'show',:controller=>'movies'}
24. Rails Router
• Handles what controller & action pair to call for given url
• Config/routes.rb is the main router file for the entire application
o Visiting /about will call static_pagers#contact method
• Can view current route setups by running:
o Rake routes (in shell console)
25. Rails Router - REST
• REsprentational State Transfer (REST)
o Way of modelling resources and keeping consistent
urls across the web – after Roy Fieldings PhD Dissertation
• Main Features:
1. Resources (Nouns) addressable through URL
2. Standard Methods (Verb)
o GET, POST
o PUT, DELETE
26. Rails Router - REST
• Rails maps HTTP Methods to Controller Actions
o GET -> index, show, new
o POST -> create
o PUT -> update
o DELETE -> destroy
27. Rails Router - Resources
• Can automatically specify resources in
routes.rb and Rails will create 7 url mappings
routes.rb
resources: Photo
Method name in photos_controller.rb
Passed to
params hash
When you visit, localhost:3000/photos/2 (GET request), Rails will call
PhotosController#show and will pass Params[:id] = 2
29. Rails Router – Nested Resources
• Can Nest resources to model relationships
Many more powerful
routing options available:
http://guides.rubyonrails.or
g/routing.html
30. Rails Controller – Mini Twitter
• Use Scaffolding to create a Post model and
controller
• Make Posts a nested resource of Users in the
router
• Modify the PostsController to display all the
posts of a given user when visiting
/user/:id/posts
31. Mini Twitter – Posts Model
rails generate scaffold Post content:string
user_id:integer
o Use rails scaffolding to generate posts!
bundle exec rake db:migrate
Edit: app/models/post.rb
Rails s
o Submitting a post with more than 140 chars will give
error (Automatically handled by Rails!)
32. Mini Twitter – Post Route
• Routes.rb:
• rake routes (to view available routes)
33. Mini Twitter – Post Controller
• App/controllers/post_controllers.rb:
• Visiting /users/:id/posts will return all the
posts by the given user
• Correction: should be find_all_by_user_id
34. Rails Controller - Summary
• To add a new action, can use scaffolding
o rails g scaffold Model_Name type:Attribute…
Or:
1. Create route in config/routes.rb if needed"
2. Add the action (method) in the appropriate
app/controllers/*_controller.rb!
3. Ensure there is something for the action to
render in app/views/model/action.html.erb!
35. Rails Views
• Views are what ends up being displayed in
the user’s browser
• Separation of controls:
o presentation (views) vs business logic (controller)
o Usually involves the controller placing dynamically
generated data into a template and then rendering the
template into the final HTML file
• We’ll use the default ERB templating system
o Many other templating systems (haml, liquid, etc)
36. Rails Views - ERB
• Embedded Ruby (part of Ruby standard lib)
• Ruby code that generates HTML
<h1>People</h1> <h1>People</h1>
<ul> <ul>
<li>Bob</li>
<% @people.each do |person| %> <li>Joe</li>
<li><%= person.first_name %></li> <li>Mary</li>
<% end %> </ul>
</ul>
• <%= expression %>
o Substitute code element with result of the code (as string)
• <% scriptlet %>
o Executed, and most commonly used for loops/logic
37. Rails Views - Forms
• Forms allow user to input and submit data
• for_for helper in Rails
39. Rails View – CSS, Sass
• CSS used to provide styling to HTML (not
look ugly), but CSS is ugly to write
• Sass is an extension of CSS3, adding nested
rules, variables,mixins, selector inheritance,
and more
• Rails’ asset pipeline supports Sass and compiles it to CSS
40. Rails Views – Bootstrap
• CSS framework for rapid prototyping
• Make sites look non-sh***y
Before After (with Bootstrap)
• Responsive design and support cross platform devices
41. Rails Views – Install Bootstrap
• Download Bootstrap CSS:
o http://twitter.github.com/bootstrap/assets/bootstrap.zip
• Copy bootstrap.min.css and bootstrap.min.css to
/vendor/assets/stylesheets
• Copy bootstrap.min.js to /vendor/assets/javascripts
• Copy images to app/assets/images
• Edit: app/assets/stylesheets/application.css
o Add: *= require bootstrap.min to third last line
• Edit: app/assets/javascripts/application.js
o Add: *= require bootstrap.min to third last line
• The last 2 lines tells the Rails asset pipeline to include the bootstrap
css and js files when compiling all the assets
42. Rails Views - Exercise
• Modify Post views so that User’s email is
displayed instead of user_id
• App/views/posts/show.html.erb
43. Rails - Associations
• One of Rail’s most powerful features is ability
to form associations between data model
• each user potentially has many microposts
• Edit: app/models/user.rb
• Edit: app/models/post.rb
44. Rails - Associations
• Primary Key Hats:
id: 557
o Unique identifier for all objects style: "Fedora"
Hats:
id: 687
• Foreign Key style: "Cowboy"
o Relates to another row’s primary key
Hats
id: 557
style: "Fedora"
inspector_id: 35
Inspectors
id: 35
name: "John"
46. Rails – Models and Relationships
• Association is a connection between two
Active Record models
• Types of Associations:
o belongs_to
o has_one
o has_many
o has_many :through
o has_one :through
o has_and_belongs_to_many
47. Rails – Belongs To
• belongs_to :parent_class
o Sets foreign key to match primary key
• Convention is parent_id is foreign_key field in child class
48. Rails – Has Many
• has_many :child_class (plural)
o Builds Association in Rails
• Related objects contain links to one another
• Can get object’s associated objects
>> myCustomer = Customer.where(:id => 2)
>> orders = myCustomer.orders
49. Rails – Has Many Through
• Question? What if Patient has many Physicians
and Physician has many Patients?
• Need many-to-many connection via 3rd model
50. Rails – Has Many and Belongs to
Many
• Creates direct many to many relationship (via
implicit 3rd model)
• Still need to create assemblies_parts in db
via migration!
51. Rails – Followers and Following
• Many-Many relationship between Users and Users!
• Relationships is the 3 rd model needed for the many-
many relationship
52. Rails – Relationship Model
• Generate relationship model:
• Add indices for faster queries
• Run migration:
53. Rails – Relationship
• Add belongs_to in app/models/relationship.rb
• Can now call relationship.follower to get the
follower (User) in the relationship
• Same for followed
54. Rails – Followed User
• Add has_many association in app/models/user.rb
• User.followed_users looks up the relationship
objects via matching the follower_id to the User’s id,
and return the list of followed Users in the
relationships (which correspond to the User’s
followed users)
55. Rails – Followed User
• Adding some utility methods to the User model
Checks if the user is
following the other user by
seeing if the relationship
object exists
Creates a relationship to
indicate that the user is now
following the other user
56. Rails – Followers
• Add has_many association in app/models/user.rb
Relationships
already exists for
followed users,
so need another
name to indicate
―reverse
relationship‖ for
followers
• User.followers looks up the relationship objects
via matching the followed_id to the User’s id, and
return the list of follower in the relationships
(which correspond to the User’s followers)
57. Rails - Followers
• We now have all the backend needed to
implement followers and following
58. Rails – Feed (User)
• Create method to get posts from all followed
Users in app/models/user.rb
• Need to implement from_users_followed_by
method in the Post model
59. Rails – Feed (Post)
• Create from_users_followed_by method in the
Post model
• Select all the posts where the user_id matches
any one of the user_id’s in the
followed_user_ids list or equals the original
owner user’s id
60. Rails – Feed (Users) Optimization
• Previously, stored array of user’s
followed_user_ids in memory
• Optimize by using subquery and offload to DB
• But even this won’t scale forever
o May need to generate the feed asynchronously using
a background job
61. Rails - Feed
• We now have all the backend needed to
implement the feed
62. Rails - Feeds
• Further Reading
Ruby on Rails Tutorial – Michael Hartl
Section 11
63. Git Commit
git init
git add .
git commit –m ―Added followers, following and
feed of MiniTwitter‖
(optional) git remote add origin
git@github.com:<username>/MiniTwitter.git
(optional)git push –u origin master
64. Heroku – New MiniTwitter App
• Sign up for Heroku (it’s Free!) http://api.heroku.com/signup
• Install the Heroku Toolbelt https://toolbelt.heroku.com/
• Heroku login
• Heroku create
o This will create a heroku app and tell you the url of
your app
• Git push heroku master
o This’ll deploy your code to Heroku. Let it do its magic!
• Heroku run rake db:migrate
• Heroku open
65. Next Time…
• Building the front-end for followers and feed
• Implementing Ajax for follow button
• More to come...
• Stayed tuned for next term!
66. Thanks!
• It was a pleasure to create this course and
present. I enjoyed every minute of it.
• Hopefully you were able to learn something
useful and will look to using Rails in your next
project!
• If these sessions helped you, please leave a
positive note or testimonial
67. Resources
• Questions? I’d be glad to help
• henrythe9th at gmail dot com
• @henrythe9ths
• Agile Web Development with Rails—Fourth Edition
• Programming Ruby: The Pragmatic Programmers' Guide – Third
Edition
• RailsCasts
• Rails main site http://www.rubyonrails.com
• CodeSchool
• Peepcode
Editor's Notes
Show Other Slides
May need to uncomment #therubyracer gem
Rails also automatically escapes the input data to prevent SQL injections
For fun, make the site return json when visiting /user/:id/posts.json
Make sure to submit a post for user 1
Need resources: posts
Should be find_all_byAlso need to create users in db