WDE-Slides-11.pptx
Web System Development with
Ruby on Rails
Day 11(8/Dec/2013)
Project: mini twitter site
Face and Follow table
Face table for users
p Class Name: Face
p Table Name: faces (plural)
p 1 to 1 relation with users table,
p Userhas_one :face
p Face belongs_to :user
p Via user.face, if related link from face is
nil, display app/assets/images/
default_face.png file (default icon).
Structure of Face Class
Face Class:
user_id, integer (index to User)
name, string (File Name
content_type, string (MIME type name
content, blob (content of image files)
Generation of Face Class
Type the following command in 1 line;
rails generate model Face user_id:integer
name:string content_type:string
content:binary
Then, generate the database.
rake db:migrate
Setting up Relations
Add
belongs_to :user
in app/models/face.rb, then add
has_one :face
in app/models/user.rb.
Registration of faces
To register faces, we generate faces
controller which have register action.
rails generate controller faces register
views/faces/register.html.erb
Register Face Photo
<%= form_for @face, :url => /faces/update,
:html => {:multipart => true}, :method => :put do %>
User: <%= @user.handle %>
<%= file_field :file, :upload %>
<% end %>
controllers/faces_controller.rb
Prepare register method, and update method.
# GET /faces/register
# GET /faces/register.json
def register
@face = Face.new
@user = User.find( current_user.id )
end
Update method
# PUT /faces/update
# PUT /faces/update.json
def update
@face = Face.find_by_user_id( current_user.id )
@face.destroy if @face
@user = User.find( current_user.id )
if params[:file]
@file = params[:file][:upload]
if @file && @file.respond_to?(:original_filename)
face_params = {
:user_id => @user.id,
:name => @file.original_filename,
:content_type => @file.content_type,
:content => @file.read
}
@face = Face.new( face_params )
end
end
if @face.save
respond_to do |format|
format.html { redirect_toedit_user_path( :id => current_user.id ),
:notice => Face photo was successfully uploaded. }
format.json { render @user, status: :created, location: @user }
end
else
respond_to do |format|
format.html { render action: register, :alert => Failed to register face photo. }
format.json { render json: @faces.errors, status: :unprocessable_entity }
end
end
end
Update Method
If any face record had been already
registered, destroy the record, then
retrieve the new File parameter to register
new face upload.
Update = destroy and newly register.
If succeed, redirect to user registration
view.
Update method
File action in Chirps_controller
Add face image transfer action, when chirps are
displayed.
def face
face = Face.find( params[:id] )
send_data face.content, :filename => face.name,
:type=>face.content_type
end
config/routes.rb
To register and display, add two routings.
get chirps/face => chirps#face
put faces/update => faces#update
The following line should have been
generated by the generator.
put faces/register
Prepare default face file
Move default_face.png file to app/assets/
images
Index of Chirps
Add Face photo display part.
<% if chirp.user.face %>
<% face = chirp.user.face %>
<% if face.content_type =~ /^image/.*?(png|jpeg|gif)$/ %>
<%= image_tag url_for({:action => face, :id=> face.id,
:filename => face.name}), :alt => face.name
%>
<% else %>
<%= image_tag ‘default_face.png’, :alt => No Photo %>
<% end %>
<% else %>
<%= image_tag ‘default_face.png’, :alt => No Photo %>
<% end %>
Index of Chirps
Registration of Face
http://127.0.0.1:3000/faces/register
If you think you need to add link to this
path, try it by yourself.
Registration of Face
Now you should have Face photo (of the
twitter owner,) and the photo for tweets.
Arrange the links
Screen link is not well arranged.So, let us re-
arrange the screen links.
[Root view] List of Chirps
Sign out:
Edit your info
Back(to List of chirps)
Upload your photo
Back(to Edit info)
Change Password
Back(to List of chirps)
app/views/chirps/index.html.erb
Arrange the top right index;
<% if current_user %>
Hello, <%= current_user.email %>
<%= link_to(‘Sign out’, destroy_user_session_path, :method => :delete) %>
<%= link_to ‘Edit your info’, edit_user_path( :id => current_user.id ) %>
<%= link_to ‘Change Password’, edit_user_registration_path %>
<% end %>
after Edit your info path
This view is in the file app/views/users/
edit.html.erb.
So we need to arrange Back link from
<%= link_to ‘Back’, users_path %>
To
<%= link_to ‘Back’, chirps_path %>
Also in the file app/views/users/
show.html.erb.
Link: edit user upload face photo
[Root view] List of Chirps
Edit your info
Upload your photo
Back(to Edit info)
Now modify this views link;
1) hand @face info link to view/users/edit.html.erb
2) after uploading file, link back to edit users.
3) confirm uploaded face in users/show.html.erb
1) Face photo upload in edit users
Add the following in app/views/users/
_form.html.erb
<%= form_for @face, :url => /faces/update,
:html => {:multipart => true}, :method => :put do %>
<%= file_field :file, :upload %>
<% end %>
app/views/users/_form.html.erb
Users controller, edit action
So that face could be registered, @face
should be given for edit template;
# GET /users/1/edit
def edit
if @user.face
@face = Face.find(@user.face.id)
else
@face = Face.new
end
end
Users controller, edit action
2) After uploading file, link back
Check the faces_controller# update method;
It already has link back to edit user path.
3) Confirm uploaded face
Add users/face path to config/routes.rb
get users/face => users#face
Then add face method to users_controller
Add face in users/show.html.erb
<% if @user.face %>
Your face photo:
<% face = @user.face %>
<% if face.content_type =~ /^image/.*?(png|jpeg|gif)$/ %>
<%= image_tag url_for({:action => face, :id=> face.id,
:filename => face.name}), :alt => face.name %>
<% end %>
<% else %>
<%= image_tag ‘default_face.png’, :alt => No Photo %>
<% end %>
app/views/users/show.html.erb
Arranged Top chirps screen
Remove timestamp input;
Chirped_at timestamp should be given by
the system, so remove the input from
_form, and give Time.now in new method.
:chirped_at => Time.now
Tweets without photo
Now controller does not save tweets without photo.
Modify this part so that the system accept the
tweets without photo;
Chirps_controller.rb else for if params[:chirp]
[:photo]
Also, when update, user_id, chirped_at time
stamps should not be updated.
Chrips controller, create action
else
@chirp = Chirp.new( chirp_params )
@chirp.user_id = current_user.id
@chirp.chirped_at = Time.now
respond_to do |format|
if @chirp.save
format.html { redirect_to @chirp, notice: Chirp was successfully created. }
format.json { render :show, status: :created, location: @chirp }
else
format.html { render :new }
format.json { render json: @chirp.errors, status: :unprocessable_entity }
end
end
end
Chirps Controller, create action
Chirps controller, update action
# PATCH/PUT /chirps/1
# PATCH/PUT /chirps/1.json
def update
if params[:chirp][:photo]
@file = params[:chirp][:photo]
@stat = @file.tempfile.stat
p chirped_at:
p params[:chirp][:chirped_at]
respond_to do |format|
if @chirp.update_attributes(
:chirp => params[:chirp][:chirp],
:file_name => @file.original_filename,
:file_type => @file.content_type,
:photo => @file.read,
)
format.html { redirect_to @chirp, notice: Chirp was successfully updated. }
format.json { render :show, status: :ok, location: @chirp }
else
format.html { render :edit }
format.json { render json: @chirp.errors, status: :unprocessable_entity }
end
end
else
respond_to do |format|
if @chirp.update_attributes(
:chirp => params[:chirp][:chirp],
)
format.html { redirect_to @chirp, notice: Chirp was successfully updated. }
format.json { render :show, status: :ok, location: @chirp }
else
format.html { render :edit }
format.json { render json: @chirp.errors, status: :unprocessable_entity }
end
end
end
end
Chirps controller, update action
Now todays next topics: Follow
My Twitter
We have introduced face photo to my twitter, for
my case, Chirpy WEB site.
My lecture slides only covered the basic structure of
the project.I hope you extend the previous
lecture slides to realize the following features/
functions;
(1) Internationalization,
(2) Screen Division/right, top bar and footer,
(3) Top banner image display, and such.
Todays Next Topics
Today, we will add the following features;
Follows table, and list only followers
messages.
Follows Table
The structure is simple.
User Follow table(one to many
Follow Class
integer user_idFollowers id
integer to_idWhom followed
rails generate model follow user_id:integer
to_id:integer
Setting up Relations for Follows
Add
in models/follow.rb
belongs_to :user
in models/user.rb
has_many :follows
Make Controller
Do not forget migration,
rake db:migrate
Now we show all users list, and show
follow / not follow button to the list, and
then reflect this follow/not follow
selection.
First, make list view
rails generate controller follows list
Generation of Controller
List method of Follows controller
class FollowsController < ApplicationController def list @users = User.all @users -= [current_user] end end Access ControllerSo that always Logged in users could tweet and follow, to avoid current_user is nil, add the following, as is in the chirps_controller.rb; before_filter :authenticate_user! In both faces_controller.rb, andfollows_controller.rb. Views/follows/list.html.erb
Follows#list
<% if user.face.content_type =~ /^image/.*?(png|jpeg|gif)$/ %>
<%= image_tag url_for({:controller => chirps, :action => face, :id=> user.face.id,
:filename => user.face.name}), :alt => user.face.name
%>
<% else %>
<%= image_tag ‘default_face.png’, :alt => user.face.name %>
<% end %>
<% else %>
<%= image_tag ‘default_face.png’, :alt => No Name %>
<% end %>
<% end %>
Views/follows/list.html.erb
Show all users except for self
Users display except for self
Add follows information to list
Add the following one line in the list method
of follows_controller;
@follows = Follow.where( user_id: current_user.id )
Add Follow buttons
Add the following in the views/follows/
list.html.erb, in the table.
<%= form_tag “/follows/cancel/”+follow.id.to_s, :method => put do %>
<%= submit_tag “Stop Follow”, :name => Cancel %>
<% end %>
<% else %>
<%= form_tag “/follows/follow/”+user.id.to_s, :method => put do %>
<%= submit_tag “Follow”, :name => Follow %>
<% end %>
<% end %>
Config/routes.rb
Add two paths of /follows/follow, and /
follows/cancel
put follows/follow/:id => follows#follow, :as =>
follows_follow
put follows/cancel/:id => follows#cancel, :as =>
follows_cancel
Method for when Followed
# put /follows/follow
# put /follows/follow.json
def follow
follow_params = {
:to_id => params[:id],
:user_id => current_user.id
}
@follow = Follow.new( follow_params )
respond_to do |format|
if @follow.save
format.html { redirect_to follows_list_path }
format.json { render :json => @follow}
else
format.html { render action: list, :alert => Failed to follow. }
format.json { render json: @follow.errors }
end
end
end
Method for when Followed
Method for when Cancelled
# put /follows/cancel
# put /follows/cancel.json
def cancel
@follow = Follow.find_by_id( params[:id] )
@follow.destroy
redirect_to follows_list_path
end
Test run for Follows/list
Now you would have the following view, to
switch follow/stop follow selection.
Choose the followers to show chirps
Modify index action in chirps controller from
def index
@chirps = Chirp.all
end
to the following;
@follows = Follow.find_all_by_user_id( current_user.id )
@users = @follows.collect { |f| f.to_id }
@users << current_user.id @chirps = Chirp.select{|c| @users.include?( c.user_id )} @chirps = @chirps.sort_by{ |c| c[:created_at] }.reverse Choose own follows in the 1st line, then make ids list in the 2nd line, add self in the 3rd line, extract followed chirps in the 4th line, and sort in reverse order if tweeted time in the 5th line. Index action of Chirps controllerviews/chirps/index.html.erbSo that faces are always displayed, modify the face display part as the following; Now it looks like twitter, a bitHow far we should go, to get similar with the real oneWe have a lot of things to do for real twitter site. Display the elapsed time since the tweet is uploaded, instead of tweeted_at timestamp. (Also, time should be formatted) Display self-introduction. How to cope with the tweets after the users withdrawal, and such. Whatever you want to do, do them by yourself as your study challenge.
Reviews
There are no reviews yet.