Showing and editing has_many objects in Rails - ruby-on-rails

I'm trying to do something that I imagine to be very basic, but I'm very new to Rails and am not sure what sure what I'm doing wrong. I've gone through several tutorials and searched for an answer and can't find what the issue is. Would appreciate any help!
I've got Models set up so that Clients have many Projects which have many Milestones:
class Client < ActiveRecord::Base
has_many :projects, :dependent => :destroy
end
class Project < ActiveRecord::Base
belongs_to :client
has_many :milestones, :dependent => :destroy
end
class Milestone < ActiveRecord::Base
belongs_to :project
end
Routes are set up as follows:
resources :clients
resources :milestones
resources :projects do
resources :milestones
end
In projects/show.html.erb, I want to display each milestone associated with a project and also provide a form that adds new milestones on that same page. When I submit the form, it adds a new milestone (a new LI within UL.card-list), but none of the values show up. Here is the code for projects/show.html.erb:
<h2><%= #project.name %> Milestones</h2>
<ul class="card-list">
<% #project.milestones.each do |m| %>
<li>
<div class="card-header">
<%= m.date %>
</div>
<div class="card-body">
<h3 class="name"><%= m.name %></h3>
<p class="description"><%= m.description %></p>
</div>
</li>
<% end %>
<li>
<div class="card-header">
New Milestone
</div>
<div class="card-body">
<%= form_for [#project,Milestone.new] do |f| %>
<%= f.hidden_field(:project_id, value: #project.id) %>
<div class="field">
<%= f.label :milestone %>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :date %>
<%= f.date_field :date %>
</div>
<div class="actions">
<%= f.submit "Add Milestone" %>
</div>
<% end %>
</div>
</li>
</ul>
Here are the parameters that are coming through the form:
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"3D12GTH+IhwMMQDKsj2l+KXe7OBxmub3eejb3pbpWao=",
"milestone"=>{
"project_id"=>"1",
"name"=>"Test Milestone",
"description"=>"test descrip",
"date"=>"2015-06-26"
},
"commit"=>"Add Milestone",
"project_id"=>"1"
}
Milestones controller:
def create
#project = Project.find(params[:project_id])
#milestone = #project.milestones.create!(params[milestone_params])
redirect_to #project
end
private
def milestone_params
params.require(:milestone).permit(:name, :description, :completed, :date, :project_id)
end
Please let me know if there's any other info I can provide that would help. Thanks!

Since you need to support both (POST /milestones and POST /projects/:project_id/milestones) the project_id to the form:
<%= form_for [#project,Milestone.new] do |f| %>
...
<%= f.hidden_field(:project_id, value: #project_id) %>
...
<%- end -%>
Or if your resource is always nested than project_id available in the params in your controller so you can just pass it:
class MilestonesContoller < ApplicationController
def create
#milestone = Milestone.new(milestone_params)
# this part was originally omitted for brevity.
if #milestone.save
redirect_to #milestone.project
else
render :new
end
end
# don't trust params from the scary interwebs
def milestone_params
params.require(:milestone)
.permit(:project_id, :name, :description, :date)
end
end
NOTE that you actually need to integrate this code with the other actions in your controller. It is just a minimal example to show the relevant concepts. Not something which is meant as a complete copy-paste-done solution.
You can also reduce your routes file down to:
resources :clients
resources :milestones
resources :projects do
resources :milestones
end
Use the options for resources if you need to customize the routes.

Related

How can I use fields_for to update a has_many association

I am making a quiz, and I have a Survey Model, Question Model and a Choice model
I am looping over all of the questions and showing the choices for that question
there is also a column on the choices table for the answer they had given, which is what I am trying to update.
Here is my code.
SurveyController
def show
#survey = Survey.find(params[:id])
end
Survey Model
class Survey < ActiveRecord::Base
attr_accessible :name
has_many :questions
end
Question Model
class Question < ActiveRecord::Base
attr_accessible :question
has_many :choices
belongs_to :survey
end
Choice Model
class Choice < ActiveRecord::Base
attr_accessible :name
belongs_to :question
end
Survey Show View
<div class="modal-wrap">
<div class="modal-header">
<% #survey.questions.size.times do %>
<span></span>
<% end %>
</div>
<div class="modal-bodies">
<%= form_for #survey do |form| %>
<% #survey.questions.each.with_index(1) do |question, index| %>
<div class="modal-body">
<div class="title">Question <%= index %></div>
<div class="description"><%= question.question %></div>
<%= form.fields_for :choices, question.choices do |choice_fields| %>
<%= choice_fields.text_field :name %>
<% end %>
<div class="text-center">
<div class="button">Next</div>
</div>
</div>
<% end %>
<% end %>
</div>
I can't get the form_for to work properly, can someone help me get this to work please?

Rails 4 -Nested Models and Simple Form partial

I am trying to make an app in Rails 4.
I have a projects, project questions and a project answers model.
my models
class Project
has_many :project_questions, dependent: :destroy#, through: :projects
accepts_nested_attributes_for :project_questions
end
class ProjectQuestions
belongs_to :project#, counter_cache: true
has_many :project_answers, dependent: :destroy
belongs_to :user
accepts_nested_attributes_for :project_answers
end
class ProjectAnswer
belongs_to :project_question#, counter_cache: true
belongs_to :user
end
routes.rb
resources :projects do
# patch '/toggle-draft', to 'projects#toggle_draft', as: 'toggle_draft'
resources :project_questions do
resources :project_answers
end
end
In my projects_controller, I have permitted params for project questions and answers as follows:
project_question_attributes: [:title, :content, :user_id, :project_id,
project_answer_attributes: [:answer, :project_question_id]],
These params are also permitted in the Project questions and project answers controllers.
In my projects view, I want to render a partial that I have made in my project_questions view folder.
projects/show
<%= link_to 'Ask a question', new_project_question_path %> <% end %>
<%= render 'project_questions/pqps' %>
In my project_questions partial which is called _pqps, I have;
<div class="containerfluid">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<% f.simple_fields_for :project_questions, #project.project_questions.build do |f| %>
<div class="categorytitle">
<%= f.title %>
</div>
<div class="generaltext">
<%= f.content %>
</div>
<%= render 'project_answers/show' %>
<span class="editproject"> <% if current_user.id == #project.creator_id %>
<%= link_to 'Answer this question', new_project_answer_path %>
<% end %>
</span>
<% end %>
</div>
</div>
</div>
When I try this, I get an error that says:
undefined local variable or method `f' for #<#:0x0000010a11ce60>
I thought I was defining f at the beginning of the opening line of the _pqps form.
I'm really struggling to get a grip with coding. Can anyone see what I've done wrong?
You use f.simple_fields_for in pqps, but f is not defined anywhere.
You have to define it using simple_form_for somewhere. I don't know exactly where – it depends on your own needs, but if, say, the whole form is inside _pqps:
<div class="containerfluid">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<%= simple_form_for #project do |f| %>
<% f.simple_fields_for :project_questions, #project.project_questions.build do |f| %>
# ...
<% end %>
<% end %>
</div>
</div>
</div>
If form "starts" outside "_pqps" partial, then you have to pass f as a local parameter:
<%= render 'project_questions/pqps', f: f %>
projects_controller
def show
#project_questions = #project.project_questions.build
end
View
<%= simple_form_for #project_questions do |f| %>
<%= f.input :title%>
<%= f.input :content %>
<%= f.button :submit %>
<% end %>

rails 4 nested form fields_for are not displayed

I just started learning Rails 4.2. The problem is that one field in the form is not being displayed.
I have restaurant, category and a dish. While creating a dish, the category and restaurant will also be inputted via /dishes/new.
Expected behaviour: Dish, Category and Restaurant fields are displayed.
Actual behaviour: Only Dish and Category fields are displayed.
Here are my models
models/restaurant.rb
class Restaurant < ActiveRecord::Base
has_many :categories
has_many :dishes, :through => :categories
end
models/category.rb
class Category < ActiveRecord::Base
belongs_to :restaurant
has_many :dishes
end
models/dish.rb
class Dish < ActiveRecord::Base
belongs_to :category
validates :name, :price, :category, :restaurant, :presence => true
accepts_nested_attributes_for :restaurant, :category
end
dish controller
def new
# I think this is where
# I am making a mistake
#dish = Dish.new
category = #dish.build_category
restaurant = category.build_restaurant
end
def create
#dish = Dish.new(dish_params)
respond_to do |format|
if #dish.save
.... # default stuff #
end
end
end
# strong params
def dish_params
params.require(:dish).permit(:name, :description, :price, restaurant_attributes: [:name], category_attributes: [:name])
end
Dishes views/dishes/_form.html.erb
<%= form_for(#dish) do |f| %>
<% if #dish.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#dish.errors.count, "error") %> prohibited this dish from being saved:</h2>
<ul>
<% #dish.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :nameWoW %><br>
<%= f.text_area :name %>
</div>
<div class="field">
<%= f.label :description %><br>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :price %><br>
<%= f.number_field :price %>
</div>
*** The restaurant name field is not being displayed **
<%= f.fields_for :restaurant do |restaurant| %>
<div class="field">
<%= restaurant.label :Restname %><br>
<%= restaurant.text_area :name %>
</div>
<% end %>
<%= f.fields_for :category do |category| %>
<div class="field">
<%= category.label :Catname %><br>
<%= category.text_area :name %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I have followed steps from rails guide, browsed questions on stackoverflow and read some blog posts as well but havent been able to figure out whats wrong. Some micro level mistake is blocking me :( . Anyone knows whats wrong ?
Thanks in advance.
UPDATE:
Hey I found a solution.
def new
#dish = Dish.new
#dish.build_category
#dish.category.build_restaurant
end
This works well.But this is just a part of the actual solution. I had to do lot of /dish/create controller modification as well. I think the entire solution will have to be put in blog post. Otherwise it wont make any sense. I will soon be posting and updating it here.
You can add this in your dish.rb
class Dish
delegate :restaurant, to: :category
end
Or you can do
<%= f.fields_for :restaurant, #dish.category.restaurant do |restaurant| %>
<div class="field">
<%= restaurant.label :Restname %><br>
<%= restaurant.text_area :name %>
</div>
<% end %>
I think you are missing:
class Dish
belongs_to :restaurant, through: :category
end
You have it on the other side (many) but not there. You could test this by trying to output #dish.restaurant on your form (should be empty but not nil).
def new
# I think this is where
# I am making a mistake
#dish = Dish.new
category = #dish.category.build
restaurant = category.restuarant.build
end

Rails 4 Nested Form.

I am building a dynamic form for a client. A form has many form questions which has many form answers. As of now, I am able to create everything nicely in Active Admin and have it displaying through the show action on the app interface. Here is the problem I have. I want to display the form title (which is working), along with the form questions (which is working), along with input fields to submit new form answers on the fly (which is the part that is not working). I feel like I have exhausted everything when it comes to nested forms. I will post my code below.
Form
<%= form_for #form do |f| %>
<div class="field">
<h1><%= #form.name %></h1>
</div>
<%= f.fields_for :form_questions do |ff| %>
<div class="field">
<%= ff.label :title %>
<%= ff.text_field :form_answers %>
</div>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>
Here is the models
class Form < ActiveRecord::Base
has_many :form_questions, dependent: :destroy
accepts_nested_attributes_for :form_questions, allow_destroy: true
end
class FormQuestion < ActiveRecord::Base
belongs_to :form
has_many :field_types
has_many :form_answers, dependent: :destroy
accepts_nested_attributes_for :field_types
accepts_nested_attributes_for :form_answers
end
class FormAnswer < ActiveRecord::Base
belongs_to :form_question
end
And my form controller
class FormsController < ApplicationController
def new
#form = Form.new
# form_questions = #form.form_questions.build
# form_answers = form_questions.form_answers.build
end
def create
#form = Form.new(form_params)
end
def index
#forms = Form.includes(:form_questions).all
end
def show
#form = Form.find(params[:id])
end
def edit
#form = Form.find(params[:id])
end
def form_params
params.require(:form).permit(:id, :name, form_questions_attributes: [:title, form_answers_attributes: [:answer]])
end
end
Firstly,you should uncomment those two lines in your new method.I guess they are correct.
def new
#form = Form.new
#form_questions = #form.form_questions.build
#form_answers = #form_questions.form_answers.build
end
And in your create action,you are not saving the data
def create
#form = Form.new(form_params)
if #form.save
.....
else
.....
end
end
Secondly,your form code should look like this
<%= form_for #form do |f| %>
<div class="field">
<h1><%= #form.name %></h1>
</div>
<%= f.fields_for #form_questions do |ff| %>
<div class="field">
<%= ff.label :title %>
<%= ff.text_field :title %>
</div>
<%= ff.fields_for #form_answers do |fa| %> #Here comes the important step
<div class="field" %>
<%= fa.label :answer %>
<%= fa.text_field :answer %>
</div>
<% end %>
<% end %>
<div class="form-actions">
<%= f.button :submit %>
</div>
<% end %>

Ruby on Rails nested resources undefined method

I saw similar examples here. But it just doesn't work for me.
I want to create/submit an activity for post. There are several days under a post. And an activity is under a specific date. See models below.
Models:
class Post < ActiveRecord::Base
has_many :dayinposts
has_many :activitys, :through => :dayinposts
end
class Dayinpost < ActiveRecord::Base
belongs_to :post
has_many :activitys
end
class Activity < ActiveRecord::Base
belongs_to :dayinpost
end
Routes:
resources :posts do
resources :dayinposts do
resources :activitys
end
end
rake routes
post_dayinpost_activitys GET /posts/:post_id/dayinposts/:dayinpost_id/activitys(.:format) activitys#index
POST /posts/:post_id/dayinposts/:dayinpost_id/activitys(.:format) activitys#create
show.html.erb
<% #post.dayinposts.each do |dayinpost| %>
<% dayinpost.activitys.each do |activity| %>
<p>
<b>Action:</b>
<%= activity.action %>
</p>
<% end %>
<%= form_for([#post, dayinpost, dayinpost.activitys.build]) do |f| %>
<div class="field">
<%= f.label :action %><br />
<%= f.text_field :action %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
error
undefined method `post_dayinpost_activities_path' for #<#<Class:0x40cb6d8>:0x40c9890>
But I have saw it in the rake routes...
thanks in advance!
The correct pluralization for "activity" is "activities".
In your config/routes.rb you have "activitys", which is wrong.

Resources