Reputation:
Simple question for Rails gurus. Why I do have to use the following statement to insert a new Mongoid document : params[:video][:description] in the following create method of my VideosController? Why I can't use the params[:description] from the POST form? If I use it, the value becomes nil.
def create
@video = Video.new(
:title => params[:video][:title],
:description => params[:video][:description]
)
if @video.save
render 'success'
else
render 'error'
end
end
Here is the Video.rb class :
class Video
include Mongoid::Document
field :title, type: String
field :description, type: String
validates_presence_of :title
validates_presence_of :description
acts_as_url :title
end
And finaly the form view :
<%= form_for @video do |f| %>
<%= f.label :title %>
<%= f.text_field :title %>
<p/>
<%= f.label :description %>
<%= f.text_field :description %>
<%= submit_tag("Enqueue video") %>
<% end %>
I don't quite get why the form input are video[description] and not just description as expected :
<label for="video_title">Title</label>
<input id="video_title" name="video[title]" type="text" />
<p/>
<label for="video_description">Description</label>
<input id="video_description" name="video[description]" type="text" />
Upvotes: 0
Views: 798
Reputation: 5206
When you are using form_for
:
Creates a form that allows the user to create or update the attributes of a specific model object.
In your case, Video
model. To understand Rails convention:
<%= form_for @video do |f| %>
...
<%= f.text_field :description %>
...
Which results in an html tag whose name attribute is video[description]. This means that when the form is submitted, the value entered by the user will be available in the controller as params[:video][:description].
The params
variable is an instace of ActiveSupport::HashWithIndifferentAccess
, like a Hash
with a small difference, according to documentation:
This class has dubious semantics and we only have it so that people can write params[:key] instead of params[‘key’] and they get the same value for both keys.
Your params
is something like:
{"utf8"=>"✓",
"_method"=>"post",
"authenticity_token"=>"xxx",
"video"=>
{"description"=>"Video desc"}
}
Where "video"
or :video
is one of the keys of the Hash. So, params[:video]
is equivalent to params.fetch("video")
which value is {"description"=>"Video desc"}
. As you can see the value is another Hash. Finally to get the value of the description you have to params[:video][:description]
(The Rails way) or params.fetch("video").fetch("description")
, which value is "Video desc"
.
fetch
is a Ruby method of Hash
: "Returns a value from the hash for the given key."
Taking this into account:
Video.new(params[:video]) = Video.new(:description => "Video desc") = Video.new(:description => params[:video][:description])
It's easier to use conventions, but for sure you can have params[:description]
(just in case):
<%= form_for @video do |f| %>
...
<%= text_field_tag :description %>
...
Note that I'm using text_field_tag
instead of f.text_field
. In this case the html tag name will be description
in the params
Hash you will receive { "description" => 'Video desc" }
...
Take a look to Rails API documentation to understand different helpers, etc. And also review your server's log.
Upvotes: 2
Reputation: 5111
If you want to use video[:description]. Create your form like this
<%= form_for @video do |f| %>
....
<p/>
<%= f.label :description %>
<%= f.text_field :description, :name => "description" %>
....
<% end %>
Rails form_for helper name the input elements such that it becomes easy to push them into model attributes in one go like this
@video = Video.new(params[:video])
so that you don't have to do it like the way you have done
@video = Video.new(
:title => params[:video][:title],
:description => params[:video][:description]
)
Upvotes: 0