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 %>
Related
First off I'm new to rails, I have a join table Menus_orders which I'm trying to load ID's into on create.
I have this form helper which has access to Order.new(:id, :name) fields and fields_for Menus_order(:menu_id, :order_id). I can insert the menu_id from a select but I can't for the life of me figure out how to populate a hidden input with the current order_id which the form holds in #order.
look at ORDER_ID HERE
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= fields_for(#menus_order) do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
<%= i.hidden_field :order_id, :value => ORDER_ID HERE %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
Thanks, DW
You should use nested attributes for order model just apply
the conventions right & it will be handled, you can achieve this by
following example :
order.rb should be like :
class Order < ActiveRecord::Base
has_many :menu_orders
accepts_nested_attributes_for :menu_orders
end
menu_order.rb be like :
class MenuOrder < ActiveRecord::Base
belongs_to :order
end
orders/new.html
<div class="form">
<h1>Create a new order</h1>
<%= form_for #order do |f| %>
<%= f.label :name%><br>
<%= f.text_field :name%><br>
<h3>Select meals</h3>
<%= f.fields_for :menu_orders do |i| %>
<div class="field">
<%= i.select :menu_id, options_for_select(Menu.all.pluck(:id)) %>
</div>
<% end %>
<br>
<%= f.submit "Create"%><br>
<% end %>
</div>
OrdersController
class OrdersController < ApplicationController
def new
#order = Order.new
#order.menu_orders.build
end
def create
#order = Order.new(order_params)
if #order.save
redirect_to orders_path
flash[:success] = "Order created"
else
render 'new'
end
end
private
def order_params
params.require(:order).permit(:name, menu_orders_attributes: [ :menu_id, :order_id ])
end
end
I was following this RailsCast about Nested Model Form, but something seems weird.
Here is Model relationship
class Question < ActiveRecord::Base
belongs_to :survey
end
class Survey < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions
end
_form.html.erb(created by scaffold)
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<% f.fields_for :questions do |builder| %>
<div class ='question'>
<%= builder.label :content, "Question" %>
<br>
<%= builder.text_area :content, :rows => 3 %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
survey_controller.rb
# GET /surveys/new
def new
#survey = Survey.new
3.times do |i|
#survey.questions.build
end
end
I was expecting it will display like
However,it didn't display 3 blocks of question.
You've missed a very small but important part of the form - actually outputting the f.fields_for call.
You need to call <%= f.fields_for :question (note the =) to actually output the generated form.
I have two models that I would like to create with one form. I tried following this railscasts tutorial, but I just can't get the nested fields to display on the form. How can I make these nested fields appear?
Models
class Poll < ActiveRecord::Base
has_many :poll_answers, :dependent => :destroy
accepts_nested_attributes_for :poll_answers, allow_destroy: true
end
class PollAnswer < ActiveRecord::Base
belongs_to :poll
end
Controller
class PollsController < ApplicationController
def new
#poll = Poll.new
2.times { #poll.poll_answers.build }
end
private
def poll_params
params.require(:poll).permit([
:question,
poll_answers_attributes: [:answer]
])
end
end
View
<%= form_for(#poll) do |f| %>
<div class="field">
<%= f.label :question %><br>
<%= f.text_field :question %>
</div>
<% f.fields_for :poll_answers do |pa| %>
<p>Hello
<%= pa.text_field :answer %>
</p>
<% end %>
<%= debug #poll.poll_answers %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
You missed an =
<%= f.fields_for :poll_answers do |pa| %>
<p>Hello
<%= pa.text_field :answer %>
</p>
<% end %>
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
How can I make this work in Rails 2.3?
class Magazine < ActiveRecord::Base
has_many :magazinepages
end
class Magazinepage < ActiveRecord::Base
belongs_to :magazine
end
and then in the controller:
def new
#magazine = Magazine.new
#magazinepages = #magazine.magazinepages.build
end
and then the form:
<% form_for(#magazine) do |f| %>
<%= error_messages_for :magazine %>
<%= error_messages_for :magazinepages %>
<fieldset>
<legend><%= t('new_magazine') %></legend>
<p>
<%= f.label :title %>
<%= f.text_field :title %>
</p>
<fieldset>
<legend><%= t('new_magazine_pages') %>
<% f.fields_for :magazinepages do |p| %>
<p>
<%= p.label :name %>
<%= p.text_field :name %>
</p>
<p>
<%= p.file_field :filepath %>
</p>
<% end %>
</fieldset>
<p>
<%= f.submit :save %>
</p>
</fieldset>
<% end %>
problem is, if I want to submit a collection of magazinepages, activerecord complaints because it's expected a model and not an array.
create action:
def create
#magazine = Magazine.new params[:magazine]
#magazine.save ? redirect_to(#magazine) : render(:action => 'new')
end
In magazine:
accepts_nested_attributes_for :magazinepages
Magazine.new(params[:magazine]) will then handle the object hierarchy for you automatically
I'm not 100% sure what you're asking, but if you're trying to instantiate a new magazine, with many magazinepages, you'll need to iterate over each magazine page. Something like this:
def create
#magazine = Magazine.new(params[:magazine])
if params[:magazinepages]
params[:magazinepages].each do |page|
#magazine.magazinepages.build(page)
end
end
# Save the model, do your redirection or rendering invalid model etc
end