Rails simple_form pre-populated input values lost during server side form validation [duplicate] - ruby-on-rails-3

This question already has an answer here:
Rails simple_form server side validations lost URL params
(1 answer)
Closed 8 years ago.
I have a simple_form in my rails app that I want to pre-populate
some of the fields with URL parameters.
Example URL is:
http://localhost:3000/surveys/new?phone=8675309
This pre-populate the phone field corretly using this code:
<%= simple_form_for #survey, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.input :state, :required => true %>
<%= f.input :zip, :required => true %>
<%= f.input :phone, :required => true, :input_html => { :value => params['phone'] } %>
<% end %>
The problem is if the form is submitted without a required field
the form is reloaded but the phone input value is not retained.
If the form is submitted without a value for zip
the reloaded page with validation errors in red URL is now:
http://localhost:3000/surveys
If, say, the state field is correct but no zip code the form is reloaded
with an error msg saying zip is required.
The state value is retained however the phone is not.
I guess it has to do with :value => params['phone'] in the f.input for the phone.
Is there anyway I can populate the simple_form with URL paramenters
on it's initial load and have those value retained if the serverside validation fails?
Many thanks.

Remove the :value from your view:
<%= f.input :phone, :required => true %>
and use this URL:
http://localhost:3000/surveys/new?survey[phone]=8675309
That should generate the "standard" survey parameter hash expected by the controller. In my test, that works the same as if the user had typed in the value, with the usual validation handling.
Inside the controller, the hash is called params[survey] with individual parameters represented as params[survey][phone], params[survey][zip], etc.
With the help of this answer, I found that you can generate the URL with the link_to signature link_to(body, url_options = {}, html_options = {}):
<%= link_to 'New survey', { :controller => "surveys",
:action => "new",
:survey => { :phone => "8675309", :zip => "10001" } },
{ :target => "_blank" } %>
Note that url_options is the first hash, and within that hash you have a survey hash for pre-loading values. Finally comes the optional hash of html_options (where I added target="_blank" for illustration purposes).

Thanks Mark,
I re-posted this question again a while back and it was answered corretly here:
Rails simple_form server side validations lost URL params

Related

Rails: No route matches [PUT] "/blog/2"

I am creating blog application in rails. I have a common form for creating and updating blog.
This is view of edit and new.html.erb
<%= render :partial => "form"%>
This is view of _form.html.erb blog:
<%= form_for #blog do |f| %>
<%= f.text_field :title, :placeholder => "Title" %><br>
<%= f.cktext_area :article, :placeholder => "Content", :ckeditor => {:toolbar => "MyToolbar"} %>
<%= f.submit %>
<% end %>
My blog is creating successfully but I am getting error on update action. This is my edit and update action in blog controller:
def edit
#blog = Blog.find_by_slug(params[:id])
end
def update
#blog = Blog.find(params[:id]) || not_found
#blog.update_attributes(params[:blog])
redirect_to "/blogs/#{#blog.slug}"
end
When I open form from edit view, and click on update button, it throws error:
No route matches [PUT] "/blog/2"
My routes.rb is:
resources :blogs
get 'blog', to: 'blogs#index'
get '/blog/:id', to: 'blogs#show', as: 'blog'
I am not getting where it is going wrong. I tried to add "url: blogs_path" in form_for, it removes the error but doesn't save the edit changes.
Can anybody help me where I am going wrong here?
Thank you.
Okay. I dont understand why you want to go against conventions. Anyway, using form_for resource would automatically generate action URL as a PUT to /resources/:id if its an update operation.
So to override this you need to do two things.
update your routes to support this:
Add this line to your routes file:
put 'blog/:id' => 'blogs#update', :as => 'update_blog'
It is important that you put this line above your 'resources :blogs` call.
2 . specify the URL to which the form should submit:
You will need to create the form tag like this:
<%= form_for #blog, :url => update_blog_path(#blog) do |f| %>
Try this and let us know.

Validations on tableless form fields in rails 3

I am attempting to run a form destined for the app's home page, which uses simultaneously tableless and database-stored variables. I need to run validations on the form. I need to run validations, one in particular which compares two of the tableless values.
My eventual goal is to get the validations running client-side via the following gem:
https://github.com/bcardarella/client_side_validations
Initially though, I want to get the validations working upon form submission.
A first question that arises is which model should hold the mail validation logic. The homePage has to do many things, is not a model and, above all, the search results lead to a different controller.
Subsequently, although some validations are one-off and don't really need to be factored out, I would place the validation logic in app/validators/different_objects_validator.rb
class DifferentObjectsValidator < ActiveModel::Validator
def different_objects
errors.add(:different_objects, "cannot be less than quantity") unless
self.quantity >= self.different_objects
end
end
Form data is:
<%= form_tag result_quote_request_path, :method => :get do %>
Base <%= number_field :quote, :base, :size => 5 %>
Height <%= number_field :quote, :height, :size => 5 %>
Quantity <%= number_field :quote, :quantity, :size => 5, :value => 1 %>
Different source objects <%= number_field :quote, :different_objects, :size => 5, :value => 1 %>
<%= submit_tag "find", :name => nil %>
<% end -%>
Then
class Quote < ActiveRecord::Base
include ActiveModel::Validations
validates :different_objects, different_objects_valid => true
After restarting Thin web server, this results in:
ActionView::Template::Error (undefined method `name' for nil:NilClass):
But this is a bit of a red herring: without the validation, the form generates a search result
I realize many things may be wrong here. I am having trouble getting the proper focus of where the validations are invoked combined with tableless states.
Your error comes from the following:
<%= submit_tag "find", :name => nil %>
Simply do
<%= submit_tag "find" %>

simple_form - how do I create radio buttons with nested input text boxes

I'm using simple_form to render my forms and trying to get the following behavior: I want the client to choose from 3 options. In every option he supplies additional field or two.
So I'd like something like this:
Please set your preferences:
o Pay me on a specific day - [input field to get the day]
o Pay me a specific amount of money - [input field for the amount]
o Pay me on a regular basis - [radio buttons to choose between weekly/monthly basis]
I can create the radio buttons as follows, but can't add nested fields under them:
<%= simple_form_for #client, action: 'edit_payment_method' do |f| %>
<%= f.input :payment_type, label: 'Please set your preferences:',
collection: [ ['Pay me on a specific day', :specific_day],
['Pay me a specific amount of money', :specific_money],
['Pay me on a regular basis', :regular_basis]
], as: :radio_buttons %>
<%= f.button :submit, 'Submit' %>
<% end %>
What would be the best way to create the nested text boxes?
As for the fields, I don't need to send them to different controllers (per payment_type), it's fine if I send them all to one method and read the relevant values according to the payment type he chose.
Thanks! Zach
The simple_form collection_radio_buttons is likely what you want. Its options parameter accepts a block which allows you to customize what is rendered with each radio button. Take a look at the example in rdocs here.
Edited:
Here is basically what you need to do in a relatively generic way (hasn't been tested, but I'm running something similar). Put your additional controls in the partial for each radio button:
<% radio_buttons = [
{ :text => 'Pay me on a specific day', :value => :specific_day, :partial => "<textbox_partial_name>", :locals => { :any_locals => :your_partial_needs} },
{ :text => 'Pay me a specific amount of money', :value => :specific_money, :partial => "<textbox_partial_name>", :locals => { :any_locals => :your_partial_needs} },
{ :text => 'Pay me on a regular basis', :value => :regular_basis, :partial => "<radio_partial_name>", :locals => { :any_locals => :your_partial_needs} },
] %>
<%= simple_form_for #client, action: 'edit_payment_method' do |f| %>
<%= f.label t("account.update_payment_method.title") %>
<%= f.collection_radio_buttons :payment_type, (collection.collect do |r| [r[:text], r[:value], r[:partial].nil? ? "" : r[:partial], r[:locals].nil? ? {} : r[:locals]] end), :second, :first do |builder| %>
<%= builder.label{builder.radio_button(:class => 'payment_method_options') + builder.text} %>
<% unless builder.object[2].blank? %>
<%= render :partial => builder.object[2], :locals => builder.object[3] %>
<% end %>
<% end %>
<%= f.button :submit, 'Submit' %>
<% end %>
You can omit :partial for any radio button that doesn't need additional controls, along with :locals if your partial doesn't need it. There are also ways to simplify this code for your situation, but this example illustrates how to add more complex control structures to each radio button if needed.
OK.. I've managed to solve this somehow, not sure that it's the best alternative, but I'm posting it so if someone needs it in the future he at least has something to start with.
I went with creating a "regular" form using simpleform and then using JQuery to move the inner input fields (which were created regularly) next to the radio buttons.
Add JQuery support to your rails app:
add gem "jquery-rails" to your Gemfile
bundle install
rails generate jquery:install
The form I've used (regular simpleform):
Notice the class that is attached to the radio buttons and the ids that are attached to the input fields. I'll use it later to move the elements.
<%= simple_form_for #client, url: 'update_payment_data' do |f| %>
<%= f.input :payment_type, label: t('account.update_payment_method.title'),
input_html: { class: 'payment_method_options' },
collection: [ [t('account.update_payment_method.sum_based.title'), :amount],
[t('account.update_payment_method.days_in_month_based.title'), :days_in_month],
[t('account.update_payment_method.optout.title'), :optput]
], as: :radio_buttons %>
<%= f.input :payment_amount, label: "Payment amount threshold",
input_html: { id: 'payment_amount_box' } %>
<%= f.input :payment_days_in_month, label: "Payment days in month",
input_html: { id: 'payment_days_in_month_box' } %>
<%= f.button :submit, t('account.update_payment_method.update') %>
<% end %>
In the same page - the JQuery code:
<script>
$(document).ready(function() {
var amount_box = $("#payment_amount_box");
var amount_box_parent = amount_box.parent();
amount_box.detach().appendTo($(".payment_method_options:eq(0)").parent());
amount_box_parent.remove();
var dim_box = $("#payment_days_in_month_box");
var dim_box_parent = dim_box.parent();
dim_box.detach().appendTo($(".payment_method_options:eq(2)").parent());
dim_box_parent.remove();
});
</script>
I think it's pretty self-explanatory, it just looks for what is going to be the inner input fields (by id) and moves them into the appropriate place under the span that simpleform creates for each radio button.
I had to play a little bit with the css to make it look how I wanted (display:block for example), but that's more or less it.
Hope it helps.. Zach

Rendering the Devise edit Password Form

I'm trying to render the Devise edit password form within another view because I don't want to duplicate the edit pw logic.
I've tried the following (after generating the Devise views):
<%= render 'devise/passwords/edit' %>
<%= render 'devise/passwords/form' %>
And a number of other variations on render that all seem to give me the same error:
"ActionView::MissingTemplate in foo#foo
Missing partial devise/passwords/edit..."
This variation:
<%= render :file => 'devise/passwords/edit.html.erb' %>
Gave me some hope but the following error:
"undefined local variable or method `resource' for #<#:0x47ef0e0>"
around this line:
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
That makes me think I'm close (as that is code from the form that I want) but shouldn't that template be using the correct logic from the hidden Devise controller? Or do I need to do something in the routes file to get this to work?
Am I way off?
Try this:
<%= render :template => 'devise/passwords/edit',
:locals => {
:resource => my_user_model_variable,
:resource_name => my_user_model_name } %>
Where:
my_user_model_variable could be current_user
my_user_model_name could be "User"

Rails 3, Form submitting to its controller

I'm new to Rails and I've just spent another hour Googling and not finding an example.
So I have a simple form that I need to submit to an API. So I tried submitting it to the API directly but got advice that I do it in my app so I can do something with the results. Anyway, here's my simple form:
<%= form_tag(:action => 'submit') do |f| %>
<%= f.text_field :email, :value => "Your email address...", :class => "text", :id => "email", :name => 'email',
:onFocus => "change(this,'#222222'); this.value=''; this.onfocus=null;",
:size => "26" %>
<%= f.hidden_field :ref_code, :id => 'ref_code', :name => 'ref_code', :value => #referralid %>
<%= submit_tag "Enter To Win", :class => "button-positive submit" %>
<% end %>
Everything I'm seeing has forms that that use a model, I have no need to persist this data, just pass it on to the API.
So my thought was I just create an action in the home controller, where this page lives and have the action submit to it but I get a RoutingError and it's: No route matches {:action=>"submit", :controller=>"home"}
So what do I need to put in the Routes.rb? I tried:
namespace :home do
resources :submit
end
No Joy... I'm sure it's simple but I just can't find the right example.
I think that you should have a look at the ruby guides, it's very well explained (but I don't think it talks about API) and it will save you a lot of time in the future, I swear.
Not sure what you mean but I see some wired stuff, so I hope to be useful, but if you're following some tutorials from the net let us know the link.
Basically what I do is always to call an action of a controller (MVC), following this way you should have a controller (?? apis_controller ??) and call one action of it.
So you want to use form_tag instead of form_for because you're not addressing a model, therefor you want to get rid of f. and use suffix _tag (api).
<%= form_tag(send_api_path) do %>
<%= text_field_tag :email, "Your email address..." %>
<%= hidden_field_tag :ref_code, #referralid %>
<%= hidden_field_tag :api_name, 'your_api_name' %>
<%= submit_tag "Enter To Win" %>
<% end %>
Then, in your apis_controller.rb you create an action send where you send and manage your request.
#apis_controller.rb
def send
# TODO: your code here
end
Another thing is to set the routes, something like
#routes.rb
match 'apis/send' => 'apis#send', :as => :send_api
I'm sure this is not 100% working code, but it should be useful
How to call the api? I had I fast look and found this.
When you ask for help it's always good to attach the error you get, this makes it easier for people to understand the problem.