I do not understand the form_for
.
I try to implement this tutorial and I do not understand the view-code.
Moreover I dont understand the api, otherwise I wouldnt asked here..<%= form_for @user, :as => :user, :url => sign_in_path(@user) do |f| %>
:as => :user
say ?:url => sign_in_path
is clear, but why is there a (@user)
behind it?@user
in a different View
?application.html.erb
(the layout), BUT the @user
is in the user_controller.rb
and not in the application_controller.rb
.<%= form_for (User.new), ...
works well, but I think it isn't right..do |f| %>
Thanks for your help!
The form_for method automatically includes the model id as a hidden field in the form. This is used to maintain the correlation between the form data and its associated model. Some ORM systems do not use IDs on nested models so in this case you want to be able to disable the hidden id.
1.3 Helpers for Generating Form Elements Rails provides a series of helpers for generating form elements such as checkboxes, text fields, and radio buttons. These basic helpers, with names ending in _tag (such as text_field_tag and check_box_tag ), generate just a single <input> element.
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? end end
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With