At the beginning let me excuse for easy question for those who are experienced but for me it is difficult right now. In the Rails in one of the views/_form.html.erb, I want to change line below (it works):
<%= f.collection_select :user_id, User.all, :id, :email %>
into hidden field that will hold the id of the user that is logged in. I try to change it into:
<% f.hidden_field :user_id, :id %>
but it throws an error:
NoMethodError in Orders#new
undefined method `merge' for :id:Symbol
Can sb help me to solve that?
This error means that it expects a hash, but you are putting an empty symbol.
You need to send a hash
If you have the current_user method:
<%= f.hidden_field :user_id, :value => current_user.id %>
If you don't, you may use this in your controller
id = User.find(someid)
And keep the same code in the view.
The first two answers are correct. Here's why
f.hidden_field
is a method on the form object you created somewhere either in that partial or in a file/partial that includes it. The documentation linked by Hristo Georgiev is for the hidden_field
method from ActionView::Helpers::FormHelper
( link ). The one you're trying to call is from ActionView::Helpers::FormBuilder
( link )
hidden_field
works just as you seem to be expecting it to, ie
hidden_field(:user_object, :id)
these are two different methods
f.hidden_field
works a bit differently, because it already has access to some of the information used to build the hidden field. It expects a method to call on the form object and an optional hash which it converts to attributes on the hidden field (thus the :value => user.id
hash)
Assuming you had the following form
form_for(@user) do |f|
...
end
And you wanted the id to be a hidden field, you would put this within that block
f.hidden_field(:id)
That would generate the following HTML
<input type="hidden" id="user_id" name="user[id]" value="1" />
See this line from ActionView
TL;DR
You're calling the FormBuilder#hidden_field
method with the arguments expected by FormHelper#hidden_field
Use this (if you already have current_user
method available):
<%= f.hidden_field :user_id, :value => current_user.id %>
If you don't have current_user
method implemented, in your corresponding controller, you can have something like this:
@current_user = User.find(params[:user_id])
Then, in your view, you can do:
<%= f.hidden_field :user_id, :value => @current_user.id %>
After the above conversation, if you want to use session to store the user_id, then you can do something like this.
You can create a SessionsHelper
module (which you can include in your ApplicationController
) where you can define a log_in
method:
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
(You can also put this: session[:user_id] = user.id
in the create
action where you create an user.)
You can also define a current_user
method in this module:
# Returns the current logged-in user (if any).
def current_user
@current_user ||= User.find_by(id: session[:user_id])
end
Here are some other useful helper methods that you can add in this module:
# Returns true if the given user is the current user.
def current_user?(user)
user == current_user
end
# Returns true if the user is logged in, false otherwise.
def logged_in?
!current_user.nil?
end
# Logs out the current user.
def log_out
session.delete(:user_id)
@current_user = nil
end
Finally, I would suggest you to take a look at Devise gem which is a very popular authentication solution for Rails application.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.