Use form_for to save data in associated table - ruby-on-rails

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.

Related

Active Storage Can't resolve image into URL error

I have set everything up for active storage and when I add a trip with an image, the app redirects to that trips show page and I can see the image. When I lave and go back to that show page I get the error
`Can't resolve image into URL: undefined method `persisted?' for nil:NilClass`
Here is the show page for trip
<h1> Location: <%= #trip.location %> </h1>
<h2> Date Visited: <%= #trip.date %> </h2>
<%= image_tag #trip.cover_photo, :style => "max-height:300px"%>
<h2> More Photos </h2>
<%= link_to "Add a photo", new_photo_path(#trip) %> <br>
<%= link_to "Public Profile", trips_path(#user) %> <br>
Here is the new trip form
<h1>Add a new trip </h1>
<%= form_for #trip do |f| %>
<%= f.label :location %>
<%= f.text_field :location %> <br>
<%= f.label :date %>
<%= f.text_field :date %> <br>
<%= f.label :cover_photo %>
<%= f.file_field :cover_photo %> <br>
<%= f.hidden_field :user_id, :value => session[:user_id] %>
<%= f.submit "Submit" %>
<% end %>
I'm not able to see the error since the photo uploads and displays correctly at first.
Had the same issue, except that I wasn't able to display the images even once. In your case, seems that the first time you are watching a temporal image, which is deleted after you live that view.
I realize that I was forgetting to add the attachment to permitted parameters in my controller, so the image wasn't saving. Your params should look like this:
def trip_params
params.require(:trip).permit(:location, :date, :cover_photo, :user_id)
end

Cocoon: How to hide a certain column when update

I am working on a new app like SNS. And I stack the case users update the group member with Cocoon. UserGroup model includes current user but current user should not be edited, so I don't want to display current user when the user edit the group member.
I want to skip the column includes current user.
apps/views/group/edit.html.erb
<div class="formItem">
<h3>Group</h3>
<%= f.fields_for :user_products do |m| %>
<div id="links">
<%= render 'maker', f: m %>
</div>
<% end %>
<%= link_to_add_association "Add member", f, :user_products, partial: 'maker' %>
</div>
apps/views/groups/_member.html.erb
<div class="nested-fields">
<div class="formField">
<%= f.collection_select :user_id, #cofounder, :id, :username, {}, class: "founderSelect" %>
<%= link_to_remove_association "Remove member", f %>
</div>
</div>
If I understand it correctly you want to remove current_user from the cofounder selection group right?
You could do it with #cofounder.where.not(id: current_user.id)
<%= f.fields_for :user_products, f.object.user_products.where.not(user_id: current_user) do |m| %>
<div id="links">
<%= render 'maker', f: m %>
</div>
<% end %>
I got it.

Cocoon: allow users only to add not edit

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.

What Is The Best Method To Create Edit Forms?

I'm working on an application in Ruby on Rails (Ruby 2 - Rails 4 - Bootstrap 3)
I have used the simple_form gem to build the forms, like signup and register, but how do you create a form that loads an object from the database and allows a user to edit the details?
Say we had a Product table in the database and I wanted to create a form to load the details of that product into the form and allow the user to edit a product's description, price, etc.
I have had a look around but still not clear.
Thanks.
First you need to put a link from your view to the edit action where you send the product as a parameter this usually goes in your index (app/views/products/index.html.erb). It should look something like this:
<%= link_to 'Edit', edit_product_path(product) %>
Then you need to make sure you have the edit action in your Products controller (app/controllers/products_controller.rb):
def edit
end
Now your edit.html.erb (app/views/products/edit.html.erb) should look something like this:
<h1>Editing product</h1>
<%= render 'form' %>
<%= link_to 'Show', #product %> |
<%= link_to 'Back', product_path %>
And finally the form you are rendering that should be located in app/views/_form.html.erb should look like this:
<%= form_for(#product) do |f| %>
<% if #product.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#product.errors.count, "error") %> prohibited this product from being saved:</h2>
<ul>
<% #product.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_field :descriptions %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
Tip: When you generate a Scaffold with the rails generate Scaffold command, it automatically creates the edit, delete, show and new actions for your model and all the views and classes I mentioned above.
rails generate Scaffold Product name:string description:text price:decimal
Hope it helps!

Concatenate multiple fields on submit into a single array/field

I have two models: QuestionnaireResult and QuestionnaireOption.
The options are dynamic.
QuestionnaireResult has two columns: date_submitted and results. I want the results column to be some sort of array of the QuestionnaireOption and their value...
i.e.
option_id / value
1 / 50
2 / false
3 / true
I submit data using this form, however it's not complete and not working because I don't know what name to give the text_fields (undefined method 'not_sure_what_to_name_this' for #<Admin::QuestionnaireResult:0x4a5ef9>):
<%= form_for(#questionnaire_result) do |f| %>
<% if #questionnaire_result.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#questionnaire_result.errors.count, "error") %> prohibited this questionnaire_result from being saved:</h2>
<ul>
<% #questionnaire_result.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<% #questionnaire_options.each do |questionnaire_option| %>
<% if questionnaire_option.field_type == 'Textbox' %>
<div class="field">
<%= f.label questionnaire_option.option %><br />
<%= f.text_field :not_sure_what_to_name_this %>
</div>
<% elsif questionnaire_option.field_type == 'Checkbox' %>
<div class="field">
<%= f.label questionnaire_option.option %><br />
<%= f.check_box :not_sure_what_to_name_this %>
</div>
<% end %>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
What name do I give text_field and how do I go about saving the results and storing them in a column as an array? Or is there better ways of going about this?
Check out this reference, where it says:
2.2 Binding a Form to an Object
While this is an increase in comfort it is far from perfect. If Person
has many attributes to edit then we would be repeating the name of the
edited object many times. What we want to do is somehow bind a form to
a model object, which is exactly what form_for does.
It goes on to show examples and elaborate on the discussion. So, the fields you use in the form_for are that model's fields. To show an example, in:
<%= form_for Feed.new, id: "feed_add" do |f| %>
<%= f.submit "Add Feed", class: 'formlabel' %>
<%= f.text_field :feed_url, class: 'forminput', :autocomplete => :off %>
<% end %>
the model is Feed and the text_field is :feed_url, so this updates Feed.feed_url. It is returned to the controller in params[:feed]['feed_url'].
If you can show your model, I can advise further.
To follow up on the other part of your question, "how do I go about saving the results and storing them in a column as an array? Or is there better ways of going about this?", that's a bit different.
If what you want to do is build an array, you might want to use form_tag instead of form_for. form_for is specifically for models. form_tag is a more generalized interface for objects not necessarily models. You can see that in the same reference. To show an example:
<%= form_tag feeds_path, method: 'get', id: "feed_search" do %>
<%= submit_tag " Search ", feed_url: nil, class: 'formlabel' %>
<%= text_field_tag :search, params[:search], class: 'forminput', :autocomplete => :off %>
<% end %>
Here, the value of :search is returned in params[:search].
Regarding how to do it, you should return this information to your controller where it can process it. Views are for display. The controller can easily build and process the array so that it can be used in its decisions and/or routing.

Resources