form_for - Ruby on Rails
A little explanation ( form_for
documentation here):
<%= form_for @user, :as => :user, :url => sign_in_path(@user) do |f| %>
Point 1. :as => :user
This is the name used to generate the input's name (and the params' names), example:
= form_for Admin.new, as: :user do |f| #^^^^ = f.input :username# will generate an input like this:<input type='text' name='user[username]' #... /> #^^^^
Point 2. :url => sign_in_path(@user)
In the tutorial, @user
is set like this:
def sign_in @user = User.new end
Point 3. @user
available in other actions
You have to set this variable in each action you want it. It can be redundant, so you can use a before_filter in order to authenticate set the @user
variable at each action your want:
class UsersController < ApplicationController before_filter :set_user_variable def set_user_variable @user ||= User.find(session[:user_id]) if session[:user_id].present? endend
If you want to make it available everywhere in your app (implies that you must be connected to a user account to browse the app):
class ApplicationController < ActionController::Base before_filter :set_user_variable, except: [:sign_in, :login] def set_user_variable @user ||= User.find(session[:user_id]) if session[:user_id].present? end
Point 4. form_for (User.new)
We set the variable @user
in the controller and pass it as an argument to form_for
because it is a Rails Convention to never call a Model's name directly in the views, and it is deprecated to provoke SQL queries in the view.
Example:
######## WRONG# view<%= Post.find(params[:id]).title %>######## MUCH BETTER# controller's action:def show @post = Post.find(params[:id])# view<%= @post.title %>
Instance Variables set in the Action of a Controller are shared between the actions, its view and its partial views.
Point 5. do/end block in form_for
Please give your input at this point, not sure how to explain it
This part of the code is called a do/end block, it represents a piece of code that will be executed in the context of the form_for
. We use the form_for
's instance as the variable defined in the pipes, here it is |f|
. I usually don't use |f|
, it is not really relevant to me. I prefer to use this kind of variable name:
= form_for @user do |user_form_builder| = user_form_builder.input :username
Which I think is more readable and easier to understand.