ERB checkboxes with different id but same value acting weirdly - html

For my ERB, if there are checkboxes with same values but for different forms, after a new render due to create error the checkboxes for different forms with same value gets checked. It doesn't seem to matter their different ids.
I have several checkboxes for model Option with two columns :size and :color. Currently, I'm using a bigger model to accept_nested_attributes for the Option model.
In my form, for each Option, I'm putting a checkbox with hidden value for color and checkbox for size such that:
<%= form_for #big do |big| %>
<%= f.fields_for :options do |option| %>
<%= f.hidden_field :color, value: "Red" %>
<%= f.check_box :size, {}, "Small", nil %>
<% end %>
<%= f.fields_for :options do |option| %>
<%= f.hidden_field :color, value: "Blue" %>
<%= f.check_box :size, {}, "Small", nil %>
<% end %>
.....
<% end %>
The options above have each unique ids according to html and everything but just gets checked equally, which I suspect is due to the same value.
Is there any way to prevent this behaviour?

I solved the problem.
This was more deeply rooted into my shabby controller practice mixed with overusing ERB fields_for.
So for my controller, I only have one #bigmodel.options.build, and in the controller I have four f.fields_for option. The problem was that the big model had one association to the options and therefore all options were being treated equally, regardless of the html output.
Since the html output was unique, the value submission was okay - not buggy - but when something failed server side, there were myriad of problems bound to come out to html.

Related

RoR form: adding text behind input-field

I am currently working on a registration form. Users should only register with an email-adress belonging to a specific domain (e.g. "#example.com"). I want to add this domain as a text behind the email-input-field to make it clear for the users what to enter. Unfortunately it seems impossible to write something behind an input-field as rails automatically does a line break.
This is the relevant part of the form:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<%= devise_error_messages! %>
<div class="field">
<%= f.label :email %>
<%= f.text_field :email, autofocus: true %>[#example.com]
</div>
<div class="actions">
<%= f.submit "register", class: "button" %>
</div>
<% end %>
The result should look like [ ] #example.com
Also I need the email-adress to be an actual email-adress. Therefore I also need to manipulate the input e.g. "john" to "john#example.com" before saving the user to the database.
How can I achieve these two things?
The strict answer to your question is that in your controller action you are free to manipulate or set attributes on an instance before you save it.
def create
#foo = Foo.new(foo_params)
#foo.email = mangle_email(#foo.email)
if #foo.save
... # normal stuff
end
end
In your particular case, you should consider the various input scenarios (e.g., user adds the #domain on their own, etc.), since there are lots of cases where just appending something to the end of the user input is probably not what you're after.

Ruby on Rails: How do I assign a "step" attribute on a time_field to step in 30 minute intervals?

I'm using form_with to generate a html form using Ruby on Rails. In this form_with, I'm using a fields_for to generate another section of forms that are attributes of the first form.
To make things simple, though, I simply want to know how I can restrict time selections to be in 30 minute increments.
For example, I am doing:
<%= form.fields_for employee_jobs do |assign_job| %>
<%= assign_job.time_field :time_start %>
<%= end %>
How can I make it so I get a "step" attribute in the html time input node when I'm done? Right now, I'm trying to do:
<%= form.fields_for employee_jobs do |assign_job| %>
<%= assign_job.time_field(:time_start, :step=>600) %>
<%= end %>
But it's not giving me the desired result.
I found out what I needed to do. Instead of using a time_field input, you can use the time_select input, and specify steps through the minute_step keyword.
Instead of:
<%= form.fields_for employee_jobs do |assign_job| %>
<%= assign_job.time_field :time_start %>
<%= end %>
You can do:
<%= form.fields_for employee_jobs do |assign_job| %>
<%= assign_job.time_select :time_start {:minute_step => 30} %>
<%= end %>
And this solved my problem.

Rails erb get value of a text_field_tag

I have simple html.erb form like below
<table>
<%= text_field_tag :tesintg %>
<th><%= button_to 'Apply now', apply_product_index_path(:value => "Want Value of input in text field here") , method: :post %></th>
</table>
When "Apply now" button is pressed I want the value in the testing text_field_tag to be posted as query params as {"value" : "Value in the text field"}
How do I achieve this.
I think the best way to do something like that is just to create form_tag
<%= form_tag apply_product_index_path, method: :post do %>
<%= text_field_tag :teasing %>
<%= submit_tag %>
<% end %>
This will pass to your controller hash params: { teasing: 'value passed as teasing }. You can easily use it from there with params[:teasing].
You don't need to grab value from text_field_tag and put it into button.
Also remember that if you are creating new object, very ofter preferred way is to use form_for tag which uses specific model. I'm not sure what are your intentions, so i'm not going to rewrite everything that has already beed said. You can read much more in here: http://guides.rubyonrails.org/form_helpers.html

Issue with Nested Form rendering

I have a rails 4 app that has a form that looks like:
<%= form_for #store, :html => {:multipart => true} do |f| %>
<%= f.fields_for :products do |product| %>
<%= render partial: "edit_product_fields", locals: {product:product} %>
<% end %>
<%= f.submit %>
<% end %>
and the edit_product_fields partial looks like:
<select>
<option value="Textbook" <% if product.type_of == "Textbook" %>selected<% end %>>Textbook</option>
<option value="Magazine" <% if product.type_of == "Magazine" %>selected<% end %>>Magazine</option>
<option value="Book" <% if product.type_of == "Book" %>selected<% end %>>Book</option>
</select>
When I have the code like this, I get the error:
undefined method `type_of' for #<NestedForm::Builder:0x00000102304f78>
but if I change the render line to (I just made it less explicit by taking out partial:):
<%= render "edit_product_fields", locals: {product:product} %>
I get the error:
undefined local variable or method `product' for #<#<Class:0x0000010235a248>:0x0000010684b3c0>
In your first code block, you have a Builder object being stored as product.
Fortunately, Builder provides an object method so you can access the actual object that it's representing in the form:
<select>
<option value="Textbook" <%= 'selected' if product.object.type_of == "Textbook" %>>Textbook</option>
<option value="Magazine" <%= 'selected' if product.object.type_of == "Magazine" %>>Magazine</option>
<option value="Book" <%= 'selected' if product.object.type_of == "Book" %>>Book</option>
</select>
Well type_of is not a ruby method. It looks like it's an attempt to type check though... But type checking is generally frowned upon in duck-typed languages. At any rate, we can take advantage of a Rails Form Helper instead and make this code a one-liner. But first...
The reason the render is complaining about undefined local variable or methodproduct'` after your change is because the render call expects either the first argument to be a partial name and the second to be a hash of locals:
<%= render "partial_name", local1: "a", local2: "b" %>
... or it expects the the whole thing to be a hash:
<%= render partial: "partial_name", locals: { local1: "a", local2: "b" } %>
Now, back to the form helper.
What you're looking for here is the select helper. This makes the following possible:
<%= product.select :type_of, %w[Textbook Magazine Book] %>
And this will render all of the same html as you've put into your _edit_product_field.html.erb partial. So you should probably just get rid of the partial to save on rendering time and put this directly into your form.
One other, minor point. It may be less confusing to call the fields_for block variable product_form instead of product. This is to help keep in mind that this is not a Product object you're dealing with, but rather a Form Generator object. Also, you don't need to specify :multipart => true in Rails 4 forms -- Rails knows to make the form multi-part if you have a file upload element within the form body.
So putting it all together:
<%= form_for #store do |f| %>
<%= f.fields_for :products do |product_form| %>
<%= product_form.select :product, %w[Textbook Magazine Book] %>
<% end %>
<%= f.submit %>
<% end %>

Passing Multiple Parameters in a form_tag

I'm using Rails and jqPlot to display some data on a webpage. The graph needs to be flexible by date (as in, the user can select a time range, and the graph will update itself). Here's my code so far (in my View):
<%= form_tag home_event_trends_path(params[:timePeriod]), :method => 'post' do %>
<p>
<%= select_tag :timePeriod, options_for_select(["2 Hours Ago", "1 Week Ago", "3 Months Ago"], :selected => params[:timePeriod]) %>
<%= submit_tag "Refresh", :name => nil %>
</p>
<% end %>
Home is my controller, event_trends is an action, I suppose. (The path is localhost:3000/home/event_trends.3102030)
This works fine. However, I need to also pass another parameter to my controller. This webpage is already having a parameter passed to it, params[:format] (this is the 3102030 in the URL, which changes based upon what event I want to display), and I need this passed along as well. I've tried:
home_event_trends_path(params[:timePeriod][:format])
home_event_trends_path(params[:timePeriod],[:format])
home_event_trends_path(params([:timePeriod][:format]))
among others.
How do I get my controller to see multiple parameters from my View?
I see you are passing the old timePeriod using GET and the new timePeriod using POST. Is this really what you want? Why does the controller need the old timePeriod?
Since you want to display a graph - that is, you want to retrieve data, not to cause side effects - I think you should send only the new timePeriod using GET:
<%= form_tag home_event_trends_path(), :method => 'get' do %>
<p>
<%= select_tag :timePeriod, options_for_select(["2 Hours Ago", "1 Week Ago", "3 Months Ago"], :selected => params[:timePeriod]) %>
<%= select_tag :format, options_for_select([...], :selected => params[:format]) %>
<%= submit_tag "Refresh", :name => nil %>
</p>
<% end %>
Also, I agree with Anthony - you should try to change the format parameter - just look in the controller to see where it is used, and change the name.
Nothing against Idan's answer, but this was what I ended up doing (for future Googlers...)
In my View:
<%= form_tag home_event_trends_path, :method => 'get' do %>
<p>
<%= select_tag :timePeriod, options_for_select(["2 Hours Ago", "1 Week Ago", "3 Months Ago"], :selected => params[:timePeriod]) %>
<%= text_field_tag :issue, params[:issue] %>
<%= submit_tag "Refresh", :name => nil %>
</p>
<% end %>
And then in my Home Controller:
def event_trends
#eventTrend = Home.eventTrend(params[:timePeriod], params[:issue])
end
And finally, the Model:
def self.eventTrend(date, id)
# dirty work
end
This seems to work best for me. I decided to allow the URL to change for the GET request, and I'm immediately storing the issue parameter in the search box, for use later on.
Hope this helps anyone in the future!