简体   繁体   中英

How do I get values entered in my Rails to form to remain after an error occurs in the form?

I'm using Rails 5. I have a form with fields like the below

<%= form_for(@user) do |f| %>
  ...
  <div class="profileField">
    <%= f.label :first_name %><br/>
    <div class="field"><%= f.text_field :first_name, :size => 20, :class => 'textField', :tabIndex => '1' %></div>
  </div>
  ...

  <div class="profileField">
    Birthday <% if !@user.errors[:dob].empty? %><span class="profileError"> <%= @user.errors[:dob].join(', ') %></span><% end %> <br/> 
    <div class="field">
      <%= f.text_field :dob_string, :value => f.object.dob_string , :size => "20", :class => 'textField', placeholder: 'MM/DD/YYYY', :tabIndex => 1 %>
    </div>  
  </div>

When the form submits, it invokes this logic in my controller

  def update
    @user = current_user 
    @user.dob_string = user_params[:dob_string] 
    if !@user.errors.any? && @user.update_attributes(user_params)
      last_page_visited = session[:last_page_visited]  
      if !last_page_visited.nil? 
        session.delete(:last_page_visited) 
      else
        flash[:success] = "Profile updated"
      end
      redirect_to !last_page_visited.nil? ? last_page_visited : url_for(:controller => 'races', :action => 'index') and return
    end

    @country_selected = !@user.address.nil? && !@user.address.country.nil? ? @user.address.country : Country.cached_find_by_iso('US')
    @states = @country_selected.states.sort_by {|obj| obj.name}      
    render 'edit'
  end

My question is, if there is an error in my form, how do I get the original values that someone entered before submitting the form to remain instead of the values that were previuosly saved? Right now, if an error occurs, all the values the user previously entered are replaced by what was saved before.

The solution didn't work. I have a "dob" field (which is a PostGres DATE column), and hwen I entered an invalid value (eg "1234") and clicked "Save", everything saved without an error being thrown. Below is my user model. I also added the definition of my date field in my view.

class User < ActiveRecord::Base
  has_many :assignments
  has_many :roles, through: :assignments
  belongs_to :address, :autosave => true  #, dependent: :destroy 

  accepts_nested_attributes_for :address

  attr_accessor :dob_string 

  def dob_string
    @dob_string || (self.dob ? self.dob.strftime('%m/%d/%Y') : "")  
  end

  def dob_string=(dob_s)
    date = dob_s && !dob_s.empty? ? Date.strptime(dob_s, '%m/%d/%Y') : nil 
    self.dob = date
  rescue ArgumentError
    errors.add(:dob, 'The birth date is not in the correct format (MM/DD/YYYY)')
    @dob_string = dob_s
  end

  def role?(role)
    roles.any? { |r| r.name.underscore.to_sym == role.to_s.underscore.to_sym }
  end

  def admin?
    role? "Admin"
  end

  def name
    name = first_name 
    if !first_name.nil?
      name = "#{name} "
    end
    "#{name}#{last_name}" 
  end

This will happen automatically if you load the attributes into the user slightly differently. the usual way to do it is something more like this:

def update
  @user = User.new(user_params)
  if @user.save
     # do stuff for when it saves correctly
  else
     # re-display the edit page with render :edit

Note: saving returns false if there are errors, so you don't need to check errors separately from this

But I see you're only letting them update the current user... (which is good). in which case you'll want:

def update
  @user = current_user
  # applies the attributes without saving to db
  @user.assign_attributes(user_params)
  if @user.save
     # do stuff for when it saves correctly
  else
     # re-display the edit page with render :edit

Doing either of these will allow the @user object to receive the attributes entered by the user - and that will then be passed to the form and be displayed.

Note: this assumes you are using something like form_for @user in your view (you didn't include that snippet)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM