Replace one model attribute by another in rails form - ruby-on-rails

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"

Related

Routing Error uninitialized constant GradesController

I decided to start a Ruby on Rails project without scaffolding because I actually wanted to learn in the process. I have searched this site but cannot seem to find the answer to my question so I will ask here. I started a Rails project where the user enters their grades. Unfortunately, on the new grade page when the user hits Create Grade I get the error in the subject line. Here is my code for the form that I use in the new page under the grade controller.
<%= form_with(model: grade, local: true) do |f| %>
<% if grade.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(grade.errors.count, "error") %> prohibited this grade
from being saved:</h2>
<ul>
<% grade.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :assignment %>
<%= f.text_field :assignment %>
</div>
<div class="field">
<%= f.label :score %>
<%= f.text_field :score %>
<div class="actions">
<%= f.submit %>
</div>
This is my routes page:
Rails.application.routes.draw do
resources :grades
root 'grade#index'
get 'grade/index'
get 'grade/show'
get 'grade/new'
get 'grade/edit'
get 'grade/create'
get 'grade/update'
get 'grade/destroy'
# For details on the DSL available within this file, see
http://guides.rubyonrails.org/routing.html
end
If more code is needed to answer the question please let me know.
Based on the title of your question, Rails is looking for a file called app/controllers/grades_controller.rb file that defines the GradesController class.
Create the following file, and you should get to the next step
# app/controllers/grades_controller.rb
class GradesController < ApplicationController
def new
#grade = Grade.new
end
def create
# logic for persisting the grade object goes here
end
# other controller methods, here
end
In the form for a new grade, use the instance variable (the one with the # symbol) you defined in the GradesController#new method:
<%= form_with(model: #grade, local: true) do |f| %>
In your routes, this is all you should need:
Rails.application.routes.draw do
resources :grades
root 'grades#index' # not 'grade#index'
end
Controllers are plural, check the name of the controller file to ensure it's plural then check the controller class name change both from GradeController to GradesController.

Rails 4: multiple fields with same name not saving

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);

Pass value from view to controller rails

Background: I have a controller -- Recipes, which generates all the recipes I have in the db and I can click one to see the detail info of the certain recipe. In the certain recipe view, I also pass all the comments this recipe has received. Below the comments info I can just make new comments upon this recipe.
Here is the question: I of course have the recipe id ----- #recipe.id. When I fill all the comment information and click submit button, this form will post to another controller -- Comments. But I just don't know how to pass the recipe id I have in this page to the Comments controller.
Recipe Controller:
def show
#For getting the ingredient info from ingredient set
#ingredientset=IngredientSet.where("recipeid=?",set_recipe.id)
#ingredients = Array.new()
i=0
#ingredientset.each do |set|
#ingredients[i]=Ingredient.find(set.ingredientid)
i+=1
end
Recipe Information View:(I only show the part for making the comment)
<!--for adding a new comment-->
<div id="add_comment">
<%= form_for(#comment) do |f| %>
<% hidden_field .....%>
<!--Here I want to pass the #recipe.id value into the comment controller-->
<!--But I dont know should I use hidden_field or something else-->
<!--I was .net MVC developer, so I only know something like #html.hiddenfor() or #ViewBag.xxx stuff-->
<div class="field">
<%= f.label :comment %><br>
<%= f.text_field :comment %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
</div>
Also I don't know how to even get the value in the Comments controller since I'm totally new in ruby on rails.
Here is the Comments controller:
def create
#comment = Comment.new(params[:comment])
#comment.recipeid = params[:recipeid])
end
Thank you very much!
In your case, it does sound like a hidden_field tag is what you want.
So, in your form, you'd add:
f.hidden_field :recipeid, <value>
Personally, if I use a hidden_field tag, I look for another way to do this, since those tags can easily be modified in the DOM before form submission. I'd look to see if there's a way to do this in your controller itself.

Array of checkboxes in Rails

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.

form_for : how to bring 2 variables into view

How can i bring 2 variables into the view. I am newbie in Ruby on rails.
What will the sytax to bring 2 or more values into a view.
<%= form_for(#user) do |f| %>
EDIT :
<%= form_for(#user) do |f| %>
prohibited this user from being saved: </h2>
<u1>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</u1>
</div>
<% end %>
<%= debug #user %>
<div class = "field">
<%= f.label :email %><br/>
<%= f.text_field :email %>
</div>
Let's say that in the above code I want to print values from 2 objects and also submit them. How can I do that ?
Well, if you need to use 2 variables, I think it would be better to use two separate forms because they are unrelated. If two variables have relations to each other, you should use accepts_nested_attributes_for and fields_for to do work.
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-fields_for
from your above comment "I am talking about loading 2 model into one form" I think you need to use two model in one form so rails cast produce good episode on using nested model for form .
You can use accepts_nested_attributes_for for eg. for survey is one model and question is another model you can use question as nested_attributes in survey and same you can use answers model in survey model in same form.
For more you can read following link.
http://railscasts.com/episodes/196-nested-model-form-part-1?view=asciicast
I hope this will help you.
Thanks.

Resources