Cocoon: allow users only to add not edit - ruby-on-rails

I have a Ticket model, which has many Comments. In the edit view, I allow users to add comments, using cocoon. However I want to ensure that previous comments can't be edited. In the view I use a partial called indexlist to render all the previous comments (and delete them). For brevity, I haven't included that code. So in the view I have
<h1>Comments</h1>
<%= render 'comments/indexlist' %>
<br /><br />
<%= f.fields_for :comments do |tc| %>
<%= render partial: 'comment_fields', locals: {f: tc} %>
<% end %>
<div>
<%= link_to_add_association 'Add Comment', f, :comments, :class => "btn btn-primary" %>
</div>
The problem is using f.fields_for :comments do |tc| ... is that it renders each previous comment, but without it, if there are validation errors on the subform all the data is lost during the form round trip.
I'm sure there's an easy solution to this one...

I guess you'll need to have a conditional in the comment_fields
<% if f.object.user_id == current_user.id %>
<div class="field">
<%= f.label :content %>
<%= f.text_field :content %>
</div>
<% else %>
<%= f.object.content %>
<% end %>
That will let you edit your own comments.
The other way you could do it is have one form purely for the ticket and use ajax to add/edit comments rather than use cocoon and nested_attributes which would be the like the way stackoverflow works.

Related

Rails: Dynamically Building Forms and Saving Responses

I'm working on a sort of survey-style project where I need to dynamically create a form based off a Question's Choice's. I've gotten decently far but have run into some issues. Question is a simple model that has_many :choices. Choice has a polymorphic content type that can be represented by anything, in this case things like inputs, check boxes, radio buttons, etc. I want to have a survey page list the questions and choices associated with that question.
So I have this:
/views/survey/index.html.erb
<h1>Survey</h1>
<%= form_for #response do |f| %>
<% #questions.each do |question| %>
<%= f.fields_for :questions do |builder| %>
<%= render question, f: builder %>
<% end %>
<% end %>
<%= f.submit 'Get Response' %>
<% end %>
app/views/questions/_question.html.erb
<h3><%= question.title %></h3>
<% question.choices.each do |choice| %>
<%= f.fields_for "question-#{question.id}" do |builder| %>
<%= render choice, f: builder %>
<% end %>
<% end %>
And an example of a choice partial:
app/views/choice_inputs/_choice_input.html.erb
<%= f.label choice_input.label %>
<%= f.text_field choice_input.label %>
Is this the best way of going about this? The problem, at least I think, with this is the html being generated gives me form names like:response[questions][question-2][tell us more]
I also don't understand how to build a Response object to this. Should I loop through the params in my ResponseController and assign Answer's to each Question? Also how would I go about permitting each question in the params?
I could see params.require(:response).permit(:question-1, :qustion-2, :etc...) getting way out of hand. Thanks for any input on this!

Best practice for DRYing up New and Edit forms using partial

This should be an easy one, I'm a noob.
I have new and edit views for a model that use a partial to display a form. For the edit form I want to display a field that I do not want to display in the new form.
Should I be passing a local variable stating its in edit mode to the partial and use a condition in the partial to display the field?
Whats the best practice in this case to let the partial know what action called it?
This will only display the field for the new form
<%# app/views/something/_form.html.erb %>
<% form_for something do |form| %>
<%# common fields ... %>
<% if something.new_record? %>
<%= form.text_field :foo %>
<% end %>
<% end %>
If you want it on the edit form, just switch if to unless
If you are using form_for, you can use same template for both new and edit.
form_for will check if the object is persisted. If it's a new record, the action url will point to #update, if it's persisted, it will point to #create.
So, yes, your comment will work when using same template for "new" and "edit". When obj.new_record?, it is a edit form.
If possible try to avoid conditionals in your view (not always possible)
_form.html.erb
# common fields only
# ...
_new.html.erb
<%= form_for #your_model do |f| %>
<fieldset>
<% # render _form partial %>
</fieldset>
<div>
<%= f.submit "Create New XXXX" %>
</div>
<% end %>
_edit.html.erb
<%= form_for #your_model do |f| %>
<fieldset>
<% # render _form partial %>
<% # render fields that only appear for edit %>
</fieldset>
<div>
<%= f.submit "Save Changes" %>
<%= link_to 'Cancel', xxxx_path %>
</div>
<% end %>

Use form_for to save data in associated table

I am relatively new to rails - therefore the question should be very easy to answer. I tried to find a solution for the problem in other posts, but I could find it (probably because I don't know the right vocabulary right now).
Here is my question/ case:
I have two models:
1) Model one: Users
2) Model two: FreelancerData
They are connect through "User has one FreelancerData" and "FreelancerData belongs_to User". The FreelancerData contains three field "daily_rate", "status" and "user_id" (= foreign field).
Now I want to create a Form with form_for, in which I can fill in the FreelancerData for the current user.
I tried the following code, but this does not work
<% provide(:title, "Edit freelancer") %>
<div class="row">
<aside class="span4">
<section>
<%= render ('layouts/profile') %>
</section>
</aside>
<div class="span8">
<h1>Edit your profile</h1>
<h5>Please edit your current working status and your daily rate:</h5>
<%= form_for #user.freelancer_data do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :status %>
<%= f.select :status, ['Busy', 'Available'] %>
<%= f.label :daily_rate, "Daily rate in Euro ('.' and ',' are not allowed)" %>
<%= f.text_field :daily_rate %>
<%= f.submit "Save changes", class: 'btn-large btn-primary' %>
<% end -%>
<h5>If you want to change your picture, you can do it here:</h5>
<%= gravatar_for #user %>
change
</div>
</div>
So my question is: Is it possible to edit data of a associated table FreelancerData through the User Data?
Yup. You can use fields_for. Check out this link.

How to submit multiple, duplicate forms from same page in Rails - preferably with one button

In my new views page I have:
<% 10.times do %>
<%= render 'group_member_form' %>
<% end %>
Now this form contains the fields: first_name, last_name, email_address and mobile_number. Basically I want to be able to fill in the fields of all the forms in one click which then submits each into the database as a unique row/id.
What would be the easiest way to accomplish this?
Note: The number of times do is called from a variable. Any advice welcome, thanks!
You should have only one form (you should put only fields in the group_member_form partial). In your view you should have something like:
<%= form_tag "/members" do %>
<% 10.times do %>
<%= render 'group_member_form' %>
<% end %>
<%= submit_tag "Submit" %>
<% end %>
and in _group_member_form.html.erb you should have
<%= text_field_tag "members[][first_name]" %>
<%= text_field_tag "members[][last_name]" %>
<%= text_field_tag "members[][email_address]" %>
<%= text_field_tag "members[][mobile_number]" %>
This way, when the form submits, params[:members] in the controller will be an array of member hashes. So, for example, to get the email adress from the fourth member after submitting the form, you call params[:members][3][:email_adress].
To understand why I wrote _group_member_form.html.erb like this, take a glance at this:
http://guides.rubyonrails.org/form_helpers.html#understanding-parameter-naming-conventions.
You can also use accepts_nested_attributes_for in your model, and use fields_for on your form.
Submitting multiple forms, afaik, only javascript, if the forms are remote: true, and you run through each of them and then submit.
$("form.class_of_forms").each(function() {
$(this).submit();
});
Alternatively a more up to date approach using form_with and fields_for, without removing the form into a partial, could be written like this:
<%= form_with (url: end_point_path), remote: true do |form| %>
<% (1..5).each do |i| %>
<%= fields_for 'cart_items'+[i].to_s do |fields|%>
<%= fields.text_field :first_name %>
<%= fields.text_field :last_name %>
<%= fields.email_field :email_address %>
<%= fields.number_field :phone_number %>
<% end %>
<% end %>
<%= form.submit "Submit" %>
<% end %>

Rails Nested Attributes Doesn't Insert ID Correctly

I'm attempting to edit a model's nested attributes, much as outline here, replicated here:
<%= form_for #person do |person_form| %>
<%= person_form.text_field :name %>
<% for address in #person.addresses %>
<%= person_form.fields_for address, :index => address do |address_form|%>
<%= address_form.text_field :city %>
<% end %>
<% end %>
<% end %>
In my code, I have the following:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<% for subitem in #meal.meal_line_items %>
<!-- # Edit 2: I need to display information here about the subitem
Which I can't find a way to pass it to the partial, or work in
this manner for existing items
-->
<%= subitem.food.name %>
<%= subitem.food.calories %>
<%= f.fields_for subitem, :index => subitem do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<% end %>
<%= f.submit %>
<% end %>
This works great, except, when I look at the HTML, it's creating the inputs that look like the following, failing to input the correct id and instead placing the memory representation(?) of the model. As a result, an update fails:
<input type="text" value="2" size="30" name="meal[meal_line_item][#<MealLineItem:0x00000005c5d618>][servings]" id="meal_meal_line_item_#<MealLineItem:0x00000005c5d618>_servings">
EDIT:
The reason I'm attempting to do it in this method is that I need to gather some information on associations for existing meal_line_items. For example, in the area where I took out code, I have some code to the effect of:
<%= subitem.food.name %>
<%= subitem.food.calories %>
Getting this information won't work if I am using a form builder with partials, at least, not in my trials.
Edit 2:*
See the edit in the code. Here's my MealLineItem
class MealLineItem < ActiveRecord::Base
# Associations ---------------------
belongs_to :food
belongs_to :meal
end
And meal accepts_nested_attributes for the model. As you can see it belongs to both food and meal model. For the existing meal_line_item I need to do something like:
meal_line_item.food.name
Is there f. missing from <%= fields_for?
--edit
Have you tried:
<%= f.fields_for 'meal[meal_line_item][]', subitem do |line_item_form| %>
--edit
Docs say that it should work without loop too:
<%= form_for(#meal) do |f| %>
<!-- some other stuff that's irrelevant... -->
<%= f.fields_for :meal_line_items do |line_item_form| %>
<%= line_item_form.label :servings %><br/>
<%= line_item_form.text_field :servings %><br/>
<%= line_item_form.label :food_id %><br/>
<%= line_item_form.text_field :food_id %><br/>
<% end %>
<%= f.submit %>
<% end %>
Have to test this but maybe this approach?
_form
<%= form.fields_for :meal_line_items do |meal_line_item_form| %>
<% #meal.meal_line_items.each do |meal_line_item| %>
<%= render :partial => "meal_line_items/meal_line_item", :locals => { :meal_line_item_form => meal_line_item_form, :meal_line_item => meal_line_item } %>
<% end %>
<% end %>
meal_line_items/_meal_line_item.erb
<%= meal_line_item_form.label :servings %><br/>
<%= meal_line_item_form.text_field :servings %><br/>
<%= meal_line_item_form.label :food_id %><br/>
<%= meal_line_item_form.text_field :food_id %><br/>
EDIT
here's a link to an example for setting the formbuilder iterator directly (Rails 2.3.8 though). The associations between Outbreak -> Incidents -> Location should be similiar to the ones for Meal -> Meal_line_items -> Food.
AJAX update of accepts_nested_attributes_for partials
After searching high and low, I found the error. Although I was modifying the partial and was receiving a NameError it's because I was calling the partial from a helper method - exactly the same problem as stated in the following question:
rails fields_for render partial with multiple locals producing undefined variable

Resources