问题
I am working in a project where users can either have admin: true / false
. The application will only let admin users login in to the system, the other users are just clients whose settings only admins can edit. This is some sort of commerce application.(Rails 3.2.13)
I would like to keep both concepts in the same table since in the future there will possibly be the option of logging in for non-admin users and interact with their profiles, so all the logic will be already implemented.
I've got this User
resource:
ActiveRecord::Schema.define(:version => 20131204200554) do
create_table "users", :force => true do |t|
t.string "name"
t.string "surname"
t.boolean "admin"
t.string "password_digest"
t.string "email"
t.string "auth_token"
end
end
This is the user model:
class User < ActiveRecord::Base
has_secure_password
attr_accessible :name, :surname,:email, :password, :password_confirmation
validates :name, presence:true, length: { maximum:50}
validates :first_surname, presence:true, length: { maximum:50}
VALID_EMAIL_REGEX= /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true,format: { with: VALID_EMAIL_REGEX }, uniqueness: { case_sensitive:false}
validates :password, length:{minimum:6}
validates :password_confirmation, presence:true
before_save{ self.email.downcase! }
before_save :generate_auth_token
private
def generate_auth_token
self.auth_token=SecureRandom.urlsafe_base64
end
end
And I am trying to implement the functionality of User
editing, however I only want to allow the editing of name
, surname
and email
. Hence, I present only those fields in the form:
<%= form_for(@user) do |f| %>
<%= f.label :name,"Name" %>
<%= f.text_field :name %>
<%= f.label :surname,"Surname" %>
<%= f.text_field :surname %>
<%= f.label :email,"Email" %>
<%= f.text_field :email %>
<%= f.submit "Save" %>
I am trying to accomplish the goal with this code:
def update
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
# Handle a successful update.
flash[:success]="User updated successfully"
redirect_to @user
else
flash[:danger]="Error updating user"
render 'edit'
end
end
My problem is that when trying to update_attributes
I get not unexpectedly an error validating password/password_confirmation
, but since I'm using has_secure_password
, these fields do not exist in the database, only password_digest
. I am thinking about the best option to accomplish all this:
- Update
@user
object with new field values. - Reflect this change in
User
table. - Run the validations, i.e. email validation.
While using has_secure_password
. These are the options so far:
- Use of
update_attribute
(best so far).
1.1 Pro: updates theUser
table
1.2 Con: I have toupdate_attribute(field1)
for each of the fields, so more lines of code
1.3 Con: Apparently this method no longer exists in Rails 4, problem in case an upgrade is desirable in the future.
1.4 Con: No validations - Use of
@user.attributes=params[:user]
in the controller method
2.1 Pro: Updates multiple fields at once.
2.2 Con: Does not update theUser
table. - User of
update_attributes
3.1 Pro: Both multiple fields and table update
3.2 Con: Not working ( duh!)
Suggestions?
回答1:
It looks like you want to validate the presence of password on create only (also notice more concise way to validate password confirmation):
validates :password, length:{minimum:6}, confirmation: true, on: :create
You can then use update_attributes
You may want to restrict what params can be submitted by using strong params:
- Gem: https://github.com/rails/strong_parameters
- also included in Rails 4 http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters.html
来源:https://stackoverflow.com/questions/20475333/rails-update-attributes-using-has-secure-password