I have a form that has fields with same name because of the "flow" of the form.
If the member is Undergrad:
<div id="if_undergrad">
<%= f.fields_for :academic do |academic_full_degree| %>
<%= academic_full_degree.text_field :major %>
<% end %>
</div>
But, if the member is Alumni:
<div id="if_alumni">
<%= f.fields_for :academic do |alumni| %>
<%= alumni.text_field :major %>
<% end %>
</div>
And I have a jQuery to show each div if the user selects alumni/undergrad from a drop-down.
If the member selects that he is Undergrad, Rails won't save the major into the database (I assume is because the major field of Alumni is blank).
Do you know how to make it work with the same name of fields?
Any help will be appreciated. Thank you!
You can disable the fields that you don't want submit then they will not send to the backend.
Somenthing like that:
$("#if_alumni input[name*='major']").prop('disabled', true);
Related
For class
class Product
has_many :productunits
accepts_nested_attributes_for :productunits
class Productunit
belongs_to :product
belongs_to :unit
validates :product_id, presence: true
validates :unit_id, presence: true
the following form is meant only to update existing records (of what is effectively a join table), while formatting the fields in columns (one column per child) and effecting some view logic on whether the field should be shown or not.
<div class='grid-x grid-margin-x'>
<%= f.fields_for :productunits do |price_fields| %>
<div class='cell small-2 text-right'>
<h4><%# productunit.unit.name %> </h4>
<%# if productunit.unit.capacity == 2 %
2 <%= label %> <%= price_fields.number_field :price2 %>
<%# end %>
</div>
<% end %>
</div>
However a number problems are arising:
I cannot invoke the value of an attribute of record being edited (say productunit.unit.capacity)
The natural break in child records is not accessible to html tags for formatting (<div class='cell [...]). Worse, rails is throwing the child record id outside the div definition </div>
<input type="hidden" value="3" name="product[productunits_attributes][1][id]" id="product_productunits_attributes_1_id" />
<div class='cell small-2 text-right'>
submitting the form returns an error Productunits unit can't be blankwhich would be fair for a new record, but is definitely not expected when editing an existing one.
Unfortunately, the rails guide is thin in this regard.
I cannot invoke the value of an attribute of record being edited
You can get the object wrapped by a form builder or input builder though the object method:
<div class='grid-x grid-margin-x'>
<%= f.fields_for :productunits do |price_fields| %>
<div class='cell small-2 text-right'>
<h4><%= price_fields.object.unit.name %> </h4>
<% if price_fields.object.unit.capacity == 2 %
2 <%= price_fields.label :price2 %> <%= price_fields.number_field :price2 %>
<% end %>
</div>
<% end %>
</div>
2 The natural break in child records is not accessible to html tags
for formatting...
fields_for just iterates through the child records. Its just a loop. I'm guessing you just have broken html like a stray </div> tag or whatever you're doing with <%= label %>.
submitting the form returns an error Productunits unit can't be blankwhich would be fair for a new record, but is definitely not expected when editing an existing one.
You're not passing a id for the unit. Rails does not do this automatically. Either use a hidden input or the collection helpers.
<div class='grid-x grid-margin-x'>
<%= f.fields_for :productunits do |price_fields| %>
<div class='cell small-2 text-right'>
<h4><%= price_fields.object.unit.name %> </h4>
<% if price_fields.object.unit.capacity == 2 %
2 <%= price_fields.label :price2 %> <%= price_fields.number_field :price2 %>
<% end %>
<%= price_fields.collection_select(:unit_id, Unit.all, :id, :name) %>
# or
<%= price_fields.hidden_field(:unit_id) %>
</div>
<% end %>
</div>
On a side note you should name your model ProductUnit, your table product_units and use product_unit everywhere else. See the Ruby Style Guide.
I have a Lease model that has a constant of "utilities" options
model
class Lease
def self.utilities_options
["Gas", "Electric", "Trash", "Water"]
end
end
form
<% Lease.utilities_options.each do |option| %>
<div class="col-md-2">
<%= check_box_tag "lease[utilities][]", option %>
<%= f.label option %>
</div>
<% end %>
What is the best way to convert the array of selected items into a string params[:lease]["utilities"].join(",") and then when the form is displayed for editing, to reselect those options?
I am building a very simple movie review app with Rails, which does not have any authentication system.
The app has:
a User model (id, name, email), which has many Reviews and has many Comments
a Review model (id, title, image, content), which belongs to one User and has many Comments
a Comment model (id, content), which belongs to one User and belongs to one Review
Here is the _form.html.erb file for comments:
<%= bootstrap_form_for(#comment) do |f| %>
<% if #comment.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#comment.errors.count, "error") %> prohibited this comment from being saved:</h2>
<ul>
<% #comment.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.text_field :content %>
</div>
<div class="field">
<%= f.number_field :review_id %>
</div>
<div class="field">
<%= f.number_field :user_id %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
When adding/editing a comment, the user can chose the Review to which the comment will be attributed, thanks to:
<div class="field">
<%= f.number_field :review_id %>
</div>
which lets him chose between review ids.
Instead, I would like the user to be able to select the review title of the review he wants to comment upon.
I tried to modify the review model with a to_param method, but it did not solve the problem and actually created some other bugs in the app.
How can I solve the problem?
Further to ply's answer, what you have to remember is when you populate an object-based form, you're really taking a Model's attributes & populating them
form_for:
Typically, a form designed to create or update a resource reflects the
identity of the resource in several ways: (i) the url that the form is
sent to (the form element's action attribute) should result in a
request being routed to the appropriate controller action (with the
appropriate :id parameter in the case of an existing resource), (ii)
input fields should be named in such a way that in the controller
their values appear in the appropriate places within the params hash,
and (iii) for an existing record, when the form is initially
displayed, input fields corresponding to attributes of the resource
should show the current values of those attributes.
--
You are populating the Comment model object - this will have attributes defined in your database, such as body, title etc
One of the attributes in the Comment model is the review_id foreign_key
To the Comment model, it does not matter how review_id is passed to it; just that it's done. This is why it does not matter if you use a text_field to input the id directly, or if you use a select tag to help the user select the item they want
--
collection_select
<%= f.collection_select(:review_id, Review.all,
:id, :title,
{:prompt => 'Please select the review of this comment'}) %>
This will give you a select box where you can pick the review
--
Nested Route
A much better way to do this is to use a nested route, so you can set review_id from the parmas:
#config/routes.rb
resources :reviews do
resources :comments #-> /reviews/1/comments/new
end
#app/controllers/comments_controller.rb
def create
#comment = Comment.new(comment_params)
#comment.save
end
private
def comment_params
params.require(:comment).permit(:content).merge(review_id: params[:review_id])
end
Not sure if I follow, but could you just use a select tag here?
This assumes you have an instance variable named #reviews defined in your controller that will be available.
In this case #reviews could be something like Review.all
select_tag "review", options_from_collection_for_select(#reviews, "id", "title"), prompt: "Select a review"
There is 'FoodType' model which are describes types of food in restaurants. I need to make view for creating a new restaurant, and I need to have list of checkboxes in order to allow user to setup types of food for each restaurant. I want to have something like this:
<% FoodType.all.each do |food_type| %>
...
<div class="row">
<%= f.check_box :food_types[0] %>
</div>
...
<% end %>
I want to have parameters like params[restaurant][food_types][0] = true in order to make some actions after creating. Please, tell me, how can I do it? Thanks in advance.
Presumably you have a join table which joins restaurants and food types? Let's say that you have one called restaurant_food_types (with a model RestaurantFoodType), which has restaurant_id and food_type_id?
You will then have this association in restaurants:
Restaurant < ActiveRecord::Base
has_many :restaurant_food_types
has_many :food_types, :through => :restaurant_food_types
This will give you the method .food_type_ids which you can call on a restaurant to set the joins. It's this method that you should hook into in your form: it expects an array of ids, so you need to set up an array-style parameter (one where the name ends in []) You may need to use check_box_tag rather than .check_box, to access an array-style parameter name: i would do this:
<% form_for #restaurant do |f| %>
<% FoodType.all.each do |food_type| %>
...
<div class="row">
<%= check_box_tag "restaurant[food_type_ids][]", food_type.id, #restaurant.food_type_ids.include?(food_type.id) %><%= food_type.name %>
</div>
...
<% end %>
<%= f.submit "Save" %>
<% end %>
Like i say i'm using a check_box_tag here but there might be a nicer way to hook into the food_type_ids method.
Just trying to save the values of 4 checkboxes into a column named reminders to my Tickets Model.
But, either the values aren't being saved, or when I go back to edit this "Ticket" its not ale to pull the data from the db and display the true / false vaules correctly.
Any advice?
/tickets/_form.html.erb
<%= form_for(#ticket) do |f| %>
<div>
<% [ 'S.T.A.R.T', 'E.N.D.E.D', 'URGENT' , 'Repeat Request' ].each do |reminder| %>
<br><%= check_box_tag 'reminders', reminder, (params[:reminders] || {}).include (reminder) %>
<%= reminder.humanize %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Rather than using check_box_tag the way you are, change it to use your form builder object provided by form_for. It'll ensure that the name of the checkbox is correct which is your problem (I think).
Because you're not using it, the checkbox is probably taking on a different name to what rails is expecting to see, so when you submit the form, the param name won't be associated with your record and thus won't be changed. Try using
<%= f.check_box_tag :reminder %>
Rails will automatically handle whether or not it is ticked when the page loads :)