In Sinatra, routes/controllers/actions combined into one entity. In rails, these things are separate. There are seven main actions: index, show, create, new, edit, update, destroy
posts GET /posts(.:format) posts#index
POST /posts(.:format) posts#create
new_post GET /posts/new(.:format) posts#new
edit_post GET /posts/:id/edit(.:format) posts#edit
post GET /posts/:id(.:format) posts#show
PUT /posts/:id(.:format) posts#update
DELETE /posts/:id(.:format) posts#destroy
get '/posts' do
@posts = Post.all
erb :posts
end
get '/posts/:id' do
@post = Post.find(params[:id])
erb :post
end
get '/posts/new' do
@post = Post.new
erb :new_post
end
get '/posts/:id/edit' do
@post = Post.find(params[:id])
erb :new_post
end
post '/posts' do
@post = Post.create(params[:post])
redirect '/posts'
end
put '/posts/:id' do
@post = Post.find(params[:id])
@post.update_attributes(params[:post])
redirect '/posts'
end
delete '/posts/:id' do
@post = Post.find(params[:id])
@post.destroy
end
# posts_controller.rb
class PostsController < ApplicationController
# GET /posts
def index
@posts = Post.all
end
# GET /posts/1
def show
@post = Post.find(params[:id])
end
# GET /posts/new
def new
@post = Post.new
end
# GET /posts/1/edit
def edit
@post = Post.find(params[:id])
end
# POST /posts
def create
@post = Post.new(params[:post])
if @post.save
format.html { redirect_to @post, notice: 'Post was successfully created.' }
# another way to redirect redirect_to :action => 'show', :id => @entry.id
else
format.html { render action: "new" }
end
end
# PUT /posts/1
def update
@post = Post.find(params[:id])
if @post.update_attributes(params[:post])
format.html { redirect_to @post, notice: 'Post was successfully updated.' }
else
format.html { render action: "edit" }
end
end
# DELETE /posts/1
def destroy
@post = Post.find(params[:id])
@post.destroy
format.html { redirect_to posts_url }
end
end
- there are different ways to pass params, in body of post request or in the get request in URL after ?
- rails converts params to hash
- post to /products
- get request at /products?key1=value1&key2=value2
class ClientsController < ActionController::Base
# This action uses query string parameters because it gets run
# by an HTTP GET request, but this does not make any difference
# to the way in which the parameters are accessed. The URL for
# this action would look like this in order to list activated
# clients: /clients?status=activated
def index
if params[:status] == "activated"
@clients = Client.activated
else
@clients = Client.unactivated
end
end
# This action uses POST parameters. They are most likely coming
# from an HTML form which the user has submitted. The URL for
# this RESTful request will be "/clients", and the data will be
# sent as part of the request body.
def create
@client = Client.new(params[:client])
if @client.save
redirect_to @client
else
# This line overrides the default rendering behavior, which
# would have been to render the "create" view.
render :action => "new"
end
end
end
- formatting in URL params to an array: GET /clients?ids[]=1&ids[]=2&ids[]=3
#4 ways to store cookies -ActionDispatch::Session::CookieStore –> Stores everything on the client. -ActiveRecord::SessionStore –> Stores the data in a database using Active Record. -ActionDispatch::Session::CacheStore –> Stores the data in the Rails cache. -ActionDispatch::Session::MemCacheStore –> Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).
accessing session is same as Sinatra to clear a specific key, set it to nil
class ApplicationController < ActionController::Base
private
# Finds the User with the ID stored in the session with the key
# :current_user_id This is a common way to handle user login in
# a Rails application; logging in sets the session value and
# logging out removes it.
def current_user
@_current_user ||= session[:current_user_id] &&
User.find_by_id(session[:current_user_id])
end
def destroy
# Remove the user id from the session
@_current_user = session[:current_user_id] = nil
redirect_to root_url
end
end
class LoginsController < ApplicationController
def destroy
session[:current_user_id] = nil
flash[:notice] = "You have successfully logged out"
redirect_to root_url
end
end
redirect_to root_url, :notice => "You have successfully logged out"
example of flash.keep, persist flash instead of deleting
class MainController < ApplicationController
# Let's say this action corresponds to root_url, but you want
# all requests here to be redirected to UsersController#index.
# If an action sets the flash and redirects here, the values
# would normally be lost when another redirect happens, but you
# can use 'keep' to make it persist for another request.
def index
# Will persist all flash values.
flash.keep
# You can also use a key to keep only some kind of value.
# flash.keep(:notice)
redirect_to users_url
end
end
- example of flash.now, flash is by default only avail to next request, if you want flash available in the same request, use flash.now
class ClientsController < ApplicationController
def create
@client = Client.new(params[:client])
if @client.save
# ...
else
flash.now[:error] = "Could not save client"
render :action => "new"
end
end
end
- similar to sessions
cookies[:this] = that
# Given these filters
# after_filter :after
# around_filter :around
# before_filter :before
#
# The filter chain will look like:
#
# ...
# . \
# . #around (code before yield)
# . . \
# . . #before (actual filter code is run)
# . . . \
# . . . execute controller action
# . . . /
# . . ...
# . . /
# . #around (code after yield)
# . /
# #after (actual filter code is run)
#
#before
class ApplicationController < ActionController::Base
before_filter :require_login
private
def require_login
unless logged_in?
flash[:error] = "You must be logged in to access this section"
redirect_to new_login_url # halts request cycle
end
end
# The logged_in? method simply returns true if the user is logged
# in and false otherwise. It does this by "booleanizing" the
# current_user method we created previously using a double ! operator.
# Note that this is not common in Ruby and is discouraged unless you
# really mean to convert something into true or false.
def logged_in?
!!current_user
end
end
#around scope of the filter is wrapped around the controller transactional filter, if there's an error, rollback filter after effect of filter happens after the controller action
skipping a filter
class LoginsController < ApplicationController
skip_before_filter :require_login, :only => [:new, :create]
end
Let's say we want to run our helper method authenticate_user! before each request, except when creating a new user
in our application controller we would have:
before_filter authenticate_user!
in our users controller we would have:
skip_before_filter :authenticate_user!, :only => [:new, :create]
Request and Response Object objects available in every controller response.headers["Content-Type"] = "application/pdf"
outside resources:
- great overview on all the features of action controller
- http://railscasts.com/episodes/395-action-controller-walkthrough
- http://api.rubyonrails.org/ => go to Classes and click on ApplicationController, has more details on filters