Rapid Prototyping with Rails: Lesson 2, part 1
05 Oct 2014Items covered: 1. Rails Forms 2. Strong Parameters
Rails Forms
There are 3 ways to create a form 1. Pure HTML 2. Rails Forms Helpers 3. Rails model-backed Forms Helpers
- PURE HTML
<h5> Pure HTML Form </h5>
<form action='/posts' method='POST'>
Title <input type='text' name='my_title'>
<br/>
<input type='submit' class='btn btn-primary'>
</form>
Rails has something called CSFP - cross site forgery protection built into it. It tries to prevent fake forms from submitting to your website.. without token. This can be disabled in your application_controller.rb
In the above section, where it says
Title <input type='text name='my_title'>
Giving the title attribute a name called "my_title" gives you the ability refer to it as a hash. So params typed into pry would give you:
{"my_title" => "some title"}
or
params[:my_title] would give you "some title" returned
*Hash with indifferent access - means although the key is a string, I can refer to it as a :symbol" So therefore, in your console, you could type:
Post.create(title: params[:my_title]) **This is called mass assignment**
- RAILS FORMS HELPERS When creating pure html forms, use form helpers.
<h4> Rails Forms Helpers </h4>
<%= form_tag '/posts' do %>
<%= label_tag :title, "Input a title" %>
<%= text_field_tag :title %>
<br/>
<%= submit_tag "Create Post", class: 'btn btn-primary' %>
<% end %>
Form helpers, do several things:
- Automatically determines the method='POST' B/c it is a form
- Security Provides an UTF 8 & authenticity token in a hidden div that helps allows us to submit under cross site forgery protection
Using the label_tag (helper) Gives more guidance to the blind. Label elements correalate with input elements and is read by screenreaders for the hearing impaired.
- RAILS MODEL-BACKED FORMS
<h4> Rails model-backed form helpers </h4>
<%= form_for @post do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<%= f.label :url %>
<% f.text_field :title %>
<br/>
<%= f.submit "Create Post", class: 'btn btn-primary' %>
<% end %>
You can mix and match forms and tags (from 2 and 3), if needed.
What is happening here:
The form_for is taking an object (@post). We must define @post in our controller:
def new
@post = Post.new
end
This gives us a few liberties:
Post.create(params[:post]) or Post.new(params[:post]) is effectively doing mass assignment,
using the hash assigned to (params[:post])
Associations
has_many :comments
has_many :posts
These become getters and setter bc they are virtual attributes as opposed to the actual column names which are actual attributes
When you have a model-backed form, you must use fields that are virtual or actual attributes because your input will attempt roll up and mass assign. This will not work if the actual attribute does not exist.
f.label :whatever (yes)
f.text_field :whatever (no)
However, the above can be accomplished with Rails Forms Helpers (#2) or Pure HTML, you can do what you want and just parse it out on the back-end.
URL
name = (post[:url]) is how rails magic, mass assignment occurs
In console or during binding.pry, typing params will list
UTf8
Authenticity Token
Post attributes in hash form
Commit
Action
Controller
Typing params[:post] is the same as post.
Strong Parameters
def create
post = Post.new(params[:post])
end
Will through an error in Rails 4 bc you don't have strong_parameters. They realized that the concern regarding strong parameters and security really didn't occur at the model layer but rather in the action based on user access, roles, etc.
So no-longer a white list of attributes available for massassignment, attraccessible :name :sex :location
So the Rails 4 version is:
def create
@post = Post.new(post_params)
end
private
def post_params #because we want to reuse this, so lets create a post_params method
params.require(:post).permit(:title, :url)
end
OR you can assign strong parameters based roles
def post_params
if user.admin?
params.require(:post).permit! #permit everything
else
params.require(:post).permit(:title, :url) #only permit title and url
end
end
If in the future, you add other input fields but do not update your strong params, it will just wipe away your entry attempt, it will not throw an error as to let hackers know what ways to pass the security restriction
So Rails 3 is attraccessible :title (whitelist) and Rails 4 is strongparams in controller action.
Now that you have understood post params, next memorize the following:
def create
@post = Post.new(post_params)
if @post.save
flash[:notice] = "Your post was created."
redirect_to posts_path
else
render 'new'
end
end