I am using cocoon gem for nested forms. My rails version is 4.2.6.
The association set between two models is as follows
Question.rb
class Question
include Mongoid::Document
field :title, type: String
has_many :choice_options, dependent: :destroy
accepts_nested_attributes_for :choice_options, :reject_if => :all_blank, :allow_destroy => true
validates :topic, presence: true
end
ChoiceOption.rb
class ChoiceOption
include Mongoid::Document
field :title, type: String
belongs_to :question
end
And I have new and question_params set as follows in questions controller
questions_controller.rb
class QuestionsController < ApplicationController
def new
#question = Question.new
end
private
def question_params
params.require(:question).permit(:title, choice_options_attributes: [:id, :title, :_destroy])
end
end
The partial form to create a new question and nested choice is as follows.
views/questions/_form.html.erb
<%= form_for #question do |f| %>
<%= render 'shared/errors', object: #question %>
<div class="form-group">
<%= f.label :title %>
<%= f.text_area :title, rows: 3, required: true, class: 'form-control' %>
</div>
<div class="panel panel-default">
<div class="panel-heading">Options</div>
<div class="panel-body">
<%= f.fields_for :choice_options do |options_form| %>
<%= render 'choice_option_fields', f: options_form %>
<% end %>
<div class="links">
<%= link_to_add_association 'add option', f, :choice_options %>
</div>
</div>
</div>
<%= f.submit 'Create', class: 'btn btn-primary btn-lg' %>
<% end %>
And then I have created a partial form for choices which I am rendering in the above page.
views/questions/_choice_option_fields.html.erb
<div class="nested-fields">
<div class="form-group">
<%= f.label :title %>
<%= f.text_field :title, class: 'form-control', required: true %>
</div>
<%= link_to_remove_association "remove option", f %>
</div>
Now when I am trying to click the add option link from the partial form, its not appearing. the url is ending at
http://localhost:3000/questions/new#
You forgot to initiate the choice options in new
class QuestionsController < ApplicationController
def new
#question = Question.new
#question.choice_options.build
end
end
Related
My _feature.html.erb looks like-
<%= error_messages_for(#project) %>
<div class="card m-auto shadow-lg p-3 mb-5 bg-white rounded">
<div class="card-body">
<%= form_for [#project, #feature], class: "form-group inline", remote: true do |builder| %>
<%= builder.hidden_field :feature_token_id, value: auto_generate_id %>
<%= builder.hidden_field :category, class: "form-control", value: category_value %>
<%= builder.label :name %>
<%= builder.text_field :name, required: true, class: "form-control" %>
<%= builder.label :desc, "Description" %>
<%= builder.text_field :desc, class: "form-control" %>
<%= builder.fields_for :task, remote: true do |form| %>
<div class="form-group">
<%= form.label :name %>
<%= form.text_field :name, required:true, class: "form-control" %>
</div>
<div class="form-check">
<%= form.check_box :completed, class: "form-check-input" %>
<%= form.label :completed %>
</div>
<div class="form-group">
<%= form.label :user_id, "Select the User to Assign this task:" %><br>
<%= form.collection_select :user_id, User.all, :id, :name %>
</div>
<% end %>
<%= builder.submit class: "btn btn-primary m-2" %>
<% end %>
</div>
</div>
And my FeaturesContrller is ->
class FeaturesController < ApplicationController
before_action :set_project
def index
#features=Feature.all
end
def new
#feature=Feature.new
#feature.tasks.new
end
def create
#feature=#project.features.new(feature_params)
binding.pry
if #feature.save
redirect_to #project
else
render "new"
end
end
private
def set_project
#project=Project.find(params[:project_id])
end
def feature_params
params.require(:feature).permit(:name, :desc, :category, :feature_token_id, tasks_attributes: [:name])
end
end
But while I try to save the form values only the Feature table gets updated but the tasks_attributes remain unpermitted instead of permitting them, what is the wrong thing I am doing?
And here is the log from pry
13: def create
14: #feature=#project.features.new(feature_params)
=> 15: binding.pry
16: if #feature.save
17: redirect_to #project
18: else
19: render "new"
20: end
21: end
[1] pry(#<FeaturesController>)> feature_params
Unpermitted parameter: :task
=> <ActionController::Parameters {"name"=>"ayann", "desc"=>"uhi", "category"=>"Current Iteration", "feature_token_id"=>"38378"} permitted: true>
[2] pry(#<FeaturesController>)>
And If I exit from pry only Feature table is updated with new value not Task table!(Log looks like)
Feature Create (0.8ms) INSERT INTO `features` (`name`, `desc`, `feature_token_id`, `project_id`, `created_at`, `updated_at`, `category`) VALUES ('ayann', 'uhi', '38378', 4, '2019-08-20 07:55:27', '2019-08-20 07:55:27', 'Current Iteration')
My feature.rb model ->
class Feature < ApplicationRecord
belongs_to :project
has_many :tasks, dependent: :destroy
accepts_nested_attributes_for :tasks
end
And task.rb model ->
class Task < ApplicationRecord
belongs_to :feature
belongs_to :user, optional: true
end
what is the reason that my nested model task is not being saved?
The problem is in the _feature.html.erb file, in building the form for accepting nested attributes for tasks. The line <%= builder.fields_for :task, remote: true do |form| %> tries to build a form for the relation task, but the Feature model has a has_many relation with tasks. Changing that line to builder.fields_for :tasks will pass the parameters as expected (as tasks_attributes and not task_attributes, which is probably being sent currently).
In my models I have
class Blog < ActiveRecord::Base
has_many :tags, :dependent => :destroy
accepts_nested_attributes_for :tags, :allow_destroy => true
end
class Tag < ActiveRecord::Base
belongs_to :blog
validates :blog, :name, presence: true
end
Blog Controller
def new
#blog = Blog.new
#blog.tags.build
end
_form.html.erb
<%= form_for #blog, html: { multipart: true } do |f| %>
<div class="form-group">
<%= f.text_field :title, placeholder: 'Title', class: ('form-control') %>
</div><br>
<%= f.fields_for :tags do |builder| %>
<div class="form-group">
<%= builder.text_field :name, placeholder: 'Tags' %>
</div><br>
<% end %>
<div class="actions text-center">
<%= f.submit 'Submit', class: 'btn btn-primary' %>
</div>
<% end %>
Blog Controller
def create
#blog = Blog.new(blog_params)
binding.pry
end
def blog_params
params.require(:blog).permit(:title, :author, :text, :avatar, :banner, :tags_attributes => [:id, :name])
end
At my binding, it says #blog's error message is that it can't be saved because the Tag object is missing a blog_id. I have looked everywhere and I have tried to replicate my code to match other solutions but to no success.
If it helps, in my params when I submit the form I get this
"tags_attributes"=>{"0"=>{"name"=>"dsfsf"}}
that's because your #blog is not persisted in the db yet, so you won't have the id.
In your Tag model, remove :id from validation.
You should be able to just do Blog.create(blog_params)
Rails should handle the rest for you.
I have a program that allows users to enter their song for a certain event. You must enter in the partycode for that event in order for it to submit. Here is a screenshot of what it looks like:
When I submit it gives me this error:
Here is what my SongsController looks like:
class SongsController < ApplicationController
def new
#song = Song.new
end
def create
current_event = Event.find(song_params[:event_id])
#song = current_event.songs.build(song_params)
if #song.save
flash[:success] = "Success"
redirect_to event_path(#song.event)
else
flash[:error] = "Failed"
end
end
def destroy
end
private
def song_params
params.require(:song).permit(:event_id, :artist, :title, :genre)
end
end
event model
class Event < ApplicationRecord
belongs_to :user
validates :name, presence: true
validates :partycode, presence: true, length: {minimum: 5}
has_many :songs, dependent: :destroy
end
song model
class Song < ApplicationRecord
belongs_to :event
validates :artist, presence: true
validates :title, presence: true
end
new.html.erb(song)
<br>
<br>
<h1> Member page </h1>
<div class ="container">
<div class="jumbotron">
<h2> Select an event to add songs to: </h2>
<%= form_for Song.new do |f| %>
<%= f.collection_select(:event_id, Event.all, :id, :name) %>
<h3> Enter your song </h3>
<%= form_for Song.new do |f| %>
<%= f.text_field :artist, placeholder: "Artist" %>
<%= f.text_field :title, placeholder: "Title" %>
<%= f.text_field :genre, placeholder: "Genre" %>
<h2> Enter the partycode for that event: </h2>
<%= form_for Event.new do |f| %>
<%= f.text_field :partycode %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
<% end %>
<% end %>
</div>
</div>
What can I do to make this functionality of my website work? Any help is greatly appreciated thanks
I see many form_for nesting on your views. It's impossible. Only one submit for a form.
I think you may want to change your _form.html.erb
<div class ="container">
<div class="jumbotron">
<h2> Select an event to add songs to: </h2>
<%= form_for #song do |f| %>
<%= f.collection_select(:event_id, Event.all, :id, :name) %>
<h3> Enter your song </h3>
<%= f.text_field :artist, placeholder: "Artist" %>
<%= f.text_field :title, placeholder: "Title" %>
<%= f.text_field :genre, placeholder: "Genre" %>
<h2> Enter the partycode for that event: </h2>
<%= f.text_field :partycode %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
You have completely messed up your form. Ideally you should have one form but here you have just kept one form within another form using form_for.
I would recommend you to have a look at the form_for documentation .
I'm using Cocoon for a nested form, however the first set of fields do not save into the database, if I create a second row they seem to save just fine?
I'm guessing its just something I'm overlooking
class Form < ActiveRecord::Base
has_many :questions
accepts_nested_attributes_for :questions, :reject_if => :all_blank, :allow_destroy => true
end
class Question < ActiveRecord::Base
belongs_to :form
end
----- form_controller.rb
def new
#form = Form.new
#form.questions.build
end
def create
#form = Form.new(form_params)
if #form.save
redirect_to action: "show", id: #form.id
else
render('new')
end
end
def form_params
params.require(:form).permit(:title, :description, :status, questions_attributes: [:form_id, :question_type, :question_text, :position, :answer_options, :validation_rules, :done, :_destroy])
end
<%= simple_form_for Form.new ,:url => {:action => :create} do |f| %>
<div class="section-row">
<div class="section-cell">
<%= f.label :title, "Form Title" %>
<%= f.text_field :title, placeholder: "Form Title" %>
<br/></br>
<%= f.label :description, "Form Description" %>
<%= f.text_area :description, placeholder: "Form Description" %>
<%= f.hidden_field :status, value: "online" %>
</div>
</div>
<div class="section-row">
<div class="section-cell">
<div id="questions">
<%= simple_fields_for :questions do |question| %>
<%= render 'question_fields', :f => question %>
<%= link_to_add_association 'add question', f, :questions %>
<% end %>
</div>
</div>
</div>
<div class="section-row">
<div class="section-cell">
<%= f.submit "Create Ticket", class: "btn btn-primary btn-lg" %>
</div>
</div>
<% end %>
---- _question_fields.html.erb
<div class='nested-fields'>
<%= f.label :question_type, "Question Type" %>
<%= f.select :question_type,
options_for_select([['Text Box','textbox'],['Dropdown Options','select'], ['Mutiple Choice','radio']], params[:question_type]),
{}, { :class => '' } %>
</div>
You forgot the f in front of the simple_fields_for : then the simple_fields_for has no knowledge of the form, nor the associations, so it will name the parameters posted to the controller differently, so it will be blocked by your strong parameters definition.
So if you write
f.simple_fields_for :questions do |question|
it should just work ;)
Smaller remarks:
the link_to_add_association should be outside of the loop, otherwise it will not be visible if there are none, and will be displayed for each question (which may or may not make sense in your UI).
you should add the id inside the strong parameters for questions_attributes (important for editing/deleting)
You wrote the link_to_add_association inside the simple_fields_for
you should write your form as follows (as documented):
<div id="questions">
<%= f.simple_fields_for :questions do |question| %>
<%= render 'question_fields', f: => question %>
<% end %>
<div class="links">
<%= link_to_add_association 'add task', f, :questions %>
</div>
I'm doing a nested form in Rails 3.2.5, but when I add the accepts_nested_attributes_for my fields_for disappear (they just stop showing in my form).
This are my models:
class Product < ActiveRecord::Base
attr_accessible :title, :description, :variants_attributes
has_many :variants
accepts_nested_attributes_for :variants
validates :title, presence: true
end
My second model is
class Variant < ActiveRecord::Base
belongs_to :product
attr_accessible :price, :sku, :weight, :inventory_quantity, :product_id
end
And in my view I have
<%= form_for [:admin, #product], :html => {:multipart => true} do |f| %>
<%= render 'admin/shared/error_messages', object: f.object %>
<fieldset>
<legend>Producto Nuevo</legend>
<div class="control-group">
<%= f.label :title, 'TÃtulo', class: 'control-label' %>
<div class="controls">
<%= f.text_field :title %>
</div>
</div>
**<%= f.fields_for :variants do |variant| %>
<%= render 'inventory_fields', f: variant %>
<% end %>**
<div class="actions">
<%= f.submit 'Guardar', class: 'btn btn-primary' %>
</div>
<% end %>
_inventory_fields.html.erb
<div class="control-group">
<%= f.label :inventory_quantity, 'How many are in stock?', class: 'control-label' %>
<div class="controls">
<%= f.text_field :inventory_quantity, class: 'span1', value: '1' %>
</div>
</div>
The part between the ** is the one that is not being printed. And when I remove accepts_nested_attributes_for in my Product model fields_for start showing again but my form won't work.
What's happening?!?!
In the controller new action call
#product.varients.build
That should create 1 in memory varient in the product varient collection and it should bind to the fields for