Rails 2.3 search form loses field values on failed validation - ruby-on-rails

I have a form that is a search form. When it fails to validate instead of retaining the field values, they are deleted and the user has to re-enter them. How can I retain the field values?
sign_in.html.erb:
<% form_tag( params.merge({ :action => "sign_in" }), :method => "post", :id => "sign_in_form" ) do %>
<div class="form_item_half">
<%= build_field_label(:user, :username, "Username") %>
<%= text_field :user, :username, :class => "text" %>
</div>
<div class="form_item_half" onKeypress="return keyRestricted(event)" onKeydown="return keyRestricted(event)">
<%= build_field_label(:user, :ssn_third, "Last four digits of Social Security Number") %>
<span id="exes">XXX-XX-</span>
<%= password_field :user, :ssn_third, :maxlength => "4", :class => 'text securitynum3', :autocomplete => "off" %>
</div>
<%= build_field_label(:user, :dob, 'Date of birth') %>
<div class="padding-bottom10 form_item_full clearfix date">
<%= select_month 14, :prompt => 'Select Month' %>
<%= text_field :dob, :day, :size => 2, :value => 'Day', :class => 'text' %>
<%= text_field :dob, :year, :size => 4, :value => 'Year', :class => 'text' %>
<div id="date_errors"></div>
</div>
<div class="padding-bottom10 form_item_full clearfix">
<%= render :partial => "/shared/captcha" %>
</div>
<div class="mp_buttons clearfix">
<input type="image" class="button" name="continue"
src="/images/v6/buttons/btn_signinsecurely.png" title="SignIn" alt="Sign In Securely">
</div>
<% end %>
onboarding_controller.rb:
def sign_in
if request.post?
flash[:errors] = Messages['onboarding/invalid_creds']; return unless #onboarding_user
flash[:errors] = Messages['onboarding/invalid_creds']; return unless params[:user][:username] == #onboarding_user.username
flash[:errors] = Messages['onboarding/invalid_creds']; return unless #onboarding_user.same_last_four?(params[:user][:ssn_third])
flash[:errors] = Messages['general/wrong_captcha']; return unless captcha_match?
unless
Date.new(params[:dob][:year].to_i, params[:date][:month].to_i, params[:dob][:day].to_i) == #onboarding_user.dob.to_date
flash[:errors] = Messages['onboarding/invalid_creds']
render :sign_in
end
session[:onboarding_user] = #onboarding_user
redirect_to :action => sign_up
end
end
If the entered values don't match what's stored in the database for #onboarding_user, then we flash an error message and render :sign_in. But this doesn't retain the field values...
#onboarding_user is loaded in a before_filter:
before_filter :load_objects_from_params, :only => :sign_in
def load_objects_from_params
#onboarding_user = OnboardingUser.find(params[:id]) unless params[:id].blank?
#onboarding_user = OnboardingUser.find_by_username(params[:user][:username]) unless #onboarding_user or request.get?
end
Here's the parameter hash seen by the controller:
Processing OnboardingController#sign_in (for 127.0.0.1 at 2013-06-18 09:17:17) [POST]
Parameters: {"authenticity_token"=>"Ij6v3x/QVZQ9pU1JPL433xMnzAJ/I4ndo+nFMCHK1Ok=", "action"=>"sign_in", "captcha_word"=>"asa", "date"=>{"month"=>"1"}, "user"=>{"username"=>"al", "ssn_third"=>"[FILTERED]"}, "continue.x"=>"-325", "continue.y"=>"-810", "controller"=>"onboarding", "dob"=>{"year"=>"12", "day"=>"1"}}
Here's the HTML that actually gets generated for the tag:
<form action="/onboarding/sign_in?authenticity_token=Ij6v3x%2FQVZQ9pU1JPL433xMnzAJ%2FI4ndo%2BnFMCHK1Ok%3D&captcha_word=asa&continue.x=-325&continue.y=-810&date%5Bmonth%5D=1&dob%5Bday%5D=1&dob%5Byear%5D=12&user%5Bssn_third%5D=3333&user%5Busername%5D=al" id="sign_in_form" method="post" novalidate="novalidate">
Any thoughts/suggestions are greatly appreciated! Thanks in advance!
Also, I'm doing client-side validation via the jQuery Validation plugin. I haven't included the code here as I don't think it's relevant, but I can provide it, if necessary.

There were actually two problems here:
I wasn't rendering the sign_in page in all the validation cases:
flash[:errors] = Messages['onboarding/invalid_creds']; render :sign_in; return unless #onboarding_user
The param names in sign_in.html.erb must be the same as the object being validated.
So, for example instead of this:
"text" %>
I needed this:
<%= text_field :onboarding_user, :username, :class => "text" %>
Hope this helps someone in the future!

Related

Rails - add elements to array using text_field

I want to do something that should be really simple: use an input text field to add elements to an array. As simple as it may seem, I'm kind of stuck...
Each User has a (single) Profile. Each Profile contains a text-field 'entertainment' that is serialized as an array in the ProfilesController.
I got as far as updating the attribute with a fixed text by using the following:
method in the ProfilesController
def update_entertainment
#user = User.find_by(params[:id])
#profile = #user.profile
#user.profile.update(entertainment: ["the usual suspects"])
redirect_to profile_path(current_user, tab:"entertainment")
end
profile_params in the ProfilesController
def profile_params
params.require(:profile).permit(:gender, :date_of_birth, :zip_code, :city, :state, :country, :marital_status, :entertainment )
end
the form
<div class="form-group">
<%= text_field :entertainment, :class => 'form-control' %>
<%= button_to("+", :action => :update_entertainment, :method => :put, :remote => true) %>
</div>
However, whatever I've tried (and that is a lot), I cannot manage to PUSH (not just update) the input of a text-field to the array. For now adding one element at a time will do. What I really want to do is give users the opportunity to ADD elements to the array.
I'm using Rails 4.0.x
The reason was in using button_to instead of usual form.
Normal form instead of button_to solved the problem.
SOLVED
With the help of #D.K. and #anushka I was able to solve the issue. I changed the changed the line
#profile.entertainment << params[:entertainment]
in the ProfilesController to
#profile.entertainment << params[:entertainment]
and changed the form to this:
<div class="form-group">
<%= form_tag(:action => :update_entertainment, :method=>'post', :multipart => true, :class => 'form-control') do %>
<div class="input-group">
<%= text_field_tag :entertainment, nil, :class => 'form-control form-group', :placeholder => 'add interests' %>
<span class="input-group-btn">
<%= submit_tag '+', class: 'btn btn-default' %>
</span>
</div>
<% end %>
</div>

Use key in params

I am trying to build a log in system by this tutorial:
http://www.youtube.com/watch?v=h0k6DFIStFY
My form looks like this:
<!DOCTYPE html>
<div id="content">
<%= flash[:alert1] %>
<%= form_for(:sessions, :url => sessions_path , :html => {:id => "login-form"}) do |f| %>
<fieldset>
<p>
<%= label_tag :name ,"Username:" %>
<%= text_field_tag :name, params[:name] , :class => "round full-width-input", :autofocus=>true %>
</p>
<p>
<%= label_tag :password, "Password:" %>
<%= password_field_tag :password, params[:password], :class => "round full-width-input" %>
</p>
<%= submit_tag "Login", :class=> "button round blue image-right ic-right-arrow" %>
</fieldset>
<% if (flash[:status] == FALSE) %>
<br/><div class="information-box round"><%= flash[:alert] %></div>
<% end %>
<% end %>
</div> <!-- end content -->
and my controller looks like this:
class SessionsController < ApplicationController
def login
end
def create
user = User.authenticated?(params[:sessions][:name], params[:sessions][:password])
flash[:alert1] = "dummy"
if user
redirect_to '/login'
else
flash[:status] = FALSE
flash[:alert] = "Invalid username and password"
redirect_to '/login'
end
end
def new
end
end
when trying to submit, i get this error:
undefined method `[]' for nil:NilClass
in the following line:
user = User.authenticated?(params[:session][:name], params[:session][:password])
Did i use incurrectly in the session key ?
Thanks,
Gal!
I think you have some problems in your form: you are using a form_for and then in fields you are using text_field_tag.
I would correct it in something like :
<% form_for sessions .... do |f| %>
<%= f.text_field :name %>
and so forth.
This will generate the params you want in your controller
params[:sessions][:name]
params[:sessions][:password]
I would suggest you to use some gem instead of building an entire system of authentication, which can be quite tricky in terms of security. Have you taken a look at https://github.com/plataformatec/devise?
Hope it helps
It looks like you're using an external authentication gem, perhaps one of these?
https://www.ruby-toolbox.com/categories/rails_authentication
You need to include a require <gem_name> line at the top.

Resetting the value of fields after submitting the ruby form

I have search field based on date entered.
The problem is whenever I am submitting the form then searched results comes good but search string disappears from the field as the page reloaded.
Can anyone tell me how to persist the search string in the field.
I am using ruby form and below is the code..
<%=form_for :messages, url: url_for( :controller => :time_sheets, :action => :late ), :html => { :id => "submitForm1" } do |f| %>
<div class="field">
<tr>
<td> From Date <%= f.text_field :leaveFrom, :id => 'datepicker2', :class => 'phcolor','data-validation' =>'required', :readonly => true %></td>
<td> To Date <%= f.text_field :leaveTo, :id => 'datepicker7', :class => 'phcolor', :readonly => true %></td>
<td >Late Time<%= f.text_field :on_duty, :id => 'timepicker5' %></td>
<div class="actions">
<td style="position: absolute;right: 178px;"><input type="button" class="btn btn-primary" id="submitid" tabindex="7" value="Go"></td>
</div>
</tr>
</div>
<% end %>
Your code form_for :messages suggests that there is an instance variable #messages, which holds the data of the fields in the form. Is there a valid #messages?
If you don't have Model for messages, I think of a simple workaround. You can add this to the action:
#messages = OpenStruct.new(params[:messages])
Or, just replace form_for with form_tag, and set value of each fields from params. form_for "creates a form and a scope around a specific model object that is used as a base for questioning about values for the fields.", which is not suitable here.
If your form isn't related to any model then use the form_tag helpers etc. Then you would do something like:
<%= text_field_tag :leaveFrom, params[:leaveFrom], :id => 'datepicker2', :class => 'phcolor','data-validation' =>'required', :readonly => true %>

Radio button value in rails form_for not being part of params[:model]

I have an model (CustInfo), which contains 3 attributes: cust_name, age, gender. In my edit view, I use form_for for form submission:
<%= form_for #cust[0] do |cust| %>
<label for="cname">Customer name: </label>
<%= cust.text_field :cust_name, :size => 20 %>
<label for="age">Customer age: </label>
<%= cust.text_field :age, :size => 5 %>
<label for="gender">Gender </label>
<%= radio_button_tag(:gender, "F", :checked => (:gender == 'female')? true:false) %><span style="float:left">F</span>
<%= radio_button_tag(:gender, "M", :checked => (:gender == 'male')? true:false) %><span style="float:left">M</span>
<%= cust.submit "Save" %>
<% end %>
In my controller I have
def update
if Cust.update_all(params[:custinfo])
flash[:notice] = "Successfully updated!"
redirect_to :action => "index"
else
flash[:notice] = "There are errors in the form, please try again"
render :action => "edit"
end
end
When I press submit button, the form submitted, and its parameters are like this:
Parameters: {"utf8"=>"✓", "authenticity_token"=>"I9QEdP1mRr65wT9TRbzNokkaa+LHVyPfmgWJMKoup", "custinfo"=>{"age"=>"16", "cust_name"=>"jsmith"}, "gender"=>"M","commit"=>"Save"}.
It looks like gender does get passed through params, but it's not within the params[:model], in this case params[:custinfo] and that's why the update function wouldn't update this value (because I only had Cust.update_all(params[:custinfo])). My question is that why only this radio button isn't in params[:custinfo], while the other two are? And how can I pass the radio button value inside params[:custinfo]? Thanks!
Try replacing your radio_button_tag calls with cust.radio_button so that Rails knows those radio buttons apply to your Customer model.
You can also simplify the :checked => (:gender == 'female')? true:false to just :checked => (:gender == 'female') because the == operator gives a boolean result.
Use cust.radio_button instead radio_button_tag

variable / dynamic content is changing based on <div> -- why?

I have some unexpected behavior in a partial, which is rendered 9 times in users/show.html.erb. (Visit www.nowdoing.com/users/2 to see what I mean.) Here is the relevant part of the partial (it's verbose for debugging purposes):
<%= "object 1 = #{object.content}" %>
<div id="float_have" style="display:none;">
<%= "object 2 = #{object.content}" %>
<%= render :partial => 'nowposts/floatpost', :locals => { :object => object.content } %>
</div>
<%= "object 3 = #{object.content}" %>
Have! |
In box #1, :object => "#nowreading book"
In box #2, :object => "#nowlistening song"
Despite this, I'm seeing the following when I load my webpage:
object 1 = "#nowreading book"
object 2 = "#nowreading book"
object 3 = "#nowreading book"
That makes sense for box#1. But the following does NOT make sense for box#2:
object 1 = "#nowlistening song"
object 2 = "#nowreading book" *** this is wrong
object 3 = "#nowlistening song"
Can someone explain to me why including putting the "#{object.content}" within the facebox DIV causes the content to change? I find this behavior very peculiar. Your help is much appreciated!
--- EDIT ---
In users/show.html.erb:
<%= render :partial => 'nowposts/nowpost',
:locals => {:object => #nowreading,
:object_link => #reading_link,
:object_mode => "reading",
:doing_img => #reading_img,
:doing_url => #reading_url_text
} %>
<%= render :partial => 'nowposts/nowpost',
:locals => {:object => #nowlistening,
:object_link => #listening_link,
:object_mode => "listening",
:doing_img => #listening_img,
:doing_url => #listening_url_text
} %>
In nowposts/_nowpost.html.erb:
<div class ="status bl br">
Fresh on <%= object.updated_at.strftime("%b %d, %Y") %><br \>
<% if user_signed_in? %>
<%= "object 1 = #{object.content}" %>
<div id="float_have" style="display:none;">
<%= "object 2 = #{object.content}" %>
<%= render :partial => 'nowposts/floatpost', :locals => { :object => object.content } %>
</div>
<div id="float_wanna" style="display:none;">
<%= "object 3 = #{object.content}" %>
<%= render :partial => 'wishlists/floatpost', :locals => { :object => object.content } %>
</div>
Have! |
Wanna!
<% end %>
</div>
In application.html.erb:
<script type="text/javascript">
jQuery(document).ready(function($) {
$('a[rel*=facebox]').facebox({
loadingImage : '../images/loading.gif',
closeImage : '../images/closelabel.png'
})
})
</script>
The partial nowposts/_floatpoast.html.erb
<h2>Wanna!</h2>
<h3>You wanna do this? Great, put it on your bucket list. </h3>
<%= form_for(:wishlist, :as => #wishlist, :url => {:controller => "wishlists", :action => "create", :user_id => current_user } ) do |f| %>
<p><%= f.label :content %><br />
<%= f.text_field :content, :value => object, :size => "80" %></p>
<p><%= f.submit "Post!" %></p>
<% end %>
As mentioned in my comment below, this code was working in my last commit (a few days ago), before I implemented caching of an API result and these nested routes:
resources :users
resources :nowposts, :only => [:have_create, :create, :new, :show]
end
But I don't think that is the problem. I just ran another test, and object.content only changes when I have it inside this div:
<div id="float_have" style="display:none;">
I tried another random div:
<div id="status">
<%= "object 2 = #{object.content}" %>
</div>
and this displayed correctly. This makes me think that the problem is the Facebox script? But if so, I wonder why it worked a few days ago.
Let me know if you need anything else.
I don't understand your code at all, it is too ambiguous. 'object' is a pretty terrible name for a variable, and content is a really bad name for an attribute. Also, your locals for the partial are rendering here doesn't make much sense ({:object => object.content}????). If you would like help, please try to clarify what this means.
That being said, can you change each debug statement from
<%= "object 1 = #{object.content}" %>
to
<%= "object 1 = #{object.inspect}" %>
<%= "object 1 content = #{object.content.inspect}" %>
and display the results.

Resources