I have an issue with simple_nested_form which use deep nesting (nesting form_field within form_field), everything works fine but while adding field by "link_to_add" it just add parent's fields not added nested fields.
Following are my has_through relationship.
customer.rb
has_many :users_customers
has_many :users, :through => :users_customers
accepts_nested_attributes_for :users_customers, allow_destroy: true
users_customer.rb
belongs_to :customer
belongs_to :user
accepts_nested_attributes_for :user
user.rb
has_many :users_customers, foreign_key: "user_id"
has_many :customers, :through => :users_customers, :dependent => :destroy
Following is my view file code: _form.html.erb under customer view.
<%= simple_nested_form_for #customer, :validate => true,:html => { class: 'form-horizontal well-white customer-detail', :multipart => 'true' } do |f| %>
<%= f.fields_for :users_customers do |user_cust| %>
<%= user_cust.fields_for :user do |u| %>
<%= u.input :first_name,as: :string, label: false, placeholder: 'Enter First Name' %>
<%= u.input :last_name,as: :string, label: false, placeholder: 'Enter Last Name' %>
<% end %>
<%= user_cust.input :role_id, collection: Role.pluck(:name,:id).reject{|t| t[1] == 4 }, label: false, placeholder: 'Select Role' %>
<% end %>
<%= f.link_to_add "Add User", :users_customers, class: "btn btn-info top-margin"%>
<% end %>
Now while click on 'add user' it just add roles dropdown not adding first_name and last_name text box.
Can anyone help me why this happen? or let me know any solution.
Thanks in advance
Related
i'm developing in Rails 4 with bootstrap rails forms and i'm trying to make a form that saves a product to a table. The product has many inputs and the input could belong to many products. The DB is postgres.
My main issue here is to save the product_id and the input_id to a join table I've created, named "productinput". this could be an example of what i'm trying to accomplish:
productinput table values example to generate each time i generate a new product with many inputs selected from a checkbox select:
product_id: 1 input_id: 1
product_id: 1 input_id: 2
product_id: 1 input_id: 3
product_id: 1 input_id: 4
I've done most of the configuration in my app. please take a look:
**productinput model**
class Productinput < ActiveRecord::Base
belongs_to :input, inverse_of: :productinputs
belongs_to :product, inverse_of: :productinputs
validates_presence_of :user_id
validates_presence_of :input_id
validates_presence_of :product_id
end
**product model**
class Product < ActiveRecord::Base
has_many :productinputs, inverse_of: :product, :dependent => :destroy
has_many :inputs, :through => :productinputs
accepts_nested_attributes_for :inputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :clientproducts, inverse_of: :product
has_many :worktasks, inverse_of: :product
validates_presence_of :user_id
accepts_nested_attributes_for :clientproducts, :allow_destroy => true
accepts_nested_attributes_for :worktasks
end
**input model**
class Input < ActiveRecord::Base
has_many :productinputs, inverse_of: :input, :dependent => :destroy
has_many :products, :through => :productinputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :inputproviders, inverse_of: :input
validates_presence_of :user_id
accepts_nested_attributes_for :inputproviders
end
Then the product form i'd like to have updated with the Input field to add inputs dinamically with a multiple select:
<%= bootstrap_form_for( #product, layout: :horizontal, label_col: "col-sm-2 hide", control_col: "col-sm-12", label_errors: true) do |f| %>
<div class="container-fluid">
<div class="row">
<%= f.alert_message "Please fix the errors below." %>
</div>
<div class="row">
<div class="col-xs-12">
<%= f.text_field :name, hide_label: true, placeholder: "Name", icon: "tag" %>
<%= f.text_field :description, hide_label: true, placeholder: "Description", icon: "align-justify" %>
<%= f.text_field :stock, hide_label: true, placeholder: "Stock", icon: "book" %>
<%= f.text_field :price, hide_label: true, placeholder: "Price", icon: "usd" %>
</div>
</div>
<div class="row text-center">
<%= f.submit "Submit Product", :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
products_path, :class => 'btn btn-default' %>
</div>
</div>
i've tried cocoon, nested_form, formtastic, simple_form gems, many tutorials and more that 2 weeks investigating this and i still don't understand how can i manage to do this, would you give me a hand please ?
Thanks,
This is how i manage to create children records in the join table from the parent form view:
Models:
class Product < ActiveRecord::Base
has_many :productinputs, :dependent => :destroy
has_many :inputs, through: :productinputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :clientproducts, inverse_of: :product
has_many :worktasks, inverse_of: :product
validates_presence_of :user_id
end
class Productinput < ActiveRecord::Base
belongs_to :product
belongs_to :input
#validates_presence_of :user_id
#validates_presence_of :input_id
#validates_presence_of :product_id
end
class Input < ActiveRecord::Base
has_many :productinputs
has_many :products, through: :productinputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :inputproviders, inverse_of: :input
validates_presence_of :user_id
accepts_nested_attributes_for :inputproviders
end
Controller:
Key here, the :inputs_ids[] fills up with an array of input elements from the "check_box_tag "product[input_ids][]"" in the form:
def product_params
parameters = params.require(:product).permit(:name, :description, :stock, :price, :input_ids => [], productinputs_attributes: [:user_id, :quantity])
parameters[:user_id] = current_user.id
parameters
end
Form:
<%= simple_form_for #product, defaults: { input_html: { class: 'form-horizontal' } } do |f| %>
<div class="row"> <%= f.error_notification id: 'user_error_message', class: 'form_error' %>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<%= f.input :name, placeholder: 'Product Name', error: 'Username is mandatory, please specify one', label: false %>
<%= f.input :description, placeholder: 'Enter Description', label: false %>
<%= f.input :stock, placeholder: 'Stock', label: false %>
<%= f.input :price, placeholder: 'Price', label: false %>
</div>
<div class="col-xs-12 col-md-6">
<%= hidden_field_tag "product[input_ids][]", nil %>
<% Input.where("user_id = ?", current_user.id).each do |input| %>
<%= check_box_tag "product[input_ids][]", input.id,
#product.input_ids.include?(input.id), id: dom_id(input) %>
<%= label_tag dom_id(input), input.name %><br>
<% end %>
</div>
</div>
<div class="row text-center">
<%= f.button :submit, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
products_path, :class => 'btn btn-default' %>
</div>
<% end %>
Hope this helps anyone who has the same issue that i did.
Sorry if some people didn't understand what i was looking for.
P.S: just to let you know, i could simplify the multiple checkbox with simple form from this:
<%= hidden_field_tag "product[input_ids][]", nil %>
<% Input.where("user_id = ?", current_user.id).each do |input| %>
<%= check_box_tag "product[input_ids][]", input.id, #product.input_ids.include?(input.id), id: dom_id(input) %>
<%= label_tag dom_id(input), input.name %><br>
<% end %>
to this:
<%= f.association :inputs, :as => :check_boxes %>
Im having problems with my child objects (scores) not being saved when submitting a form for a new (Qa).
Here are the models:
QA
belongs_to :user
has_many :scores, :dependent => :destory
has_many :call_components, through: :scores
accepts_nested_attributes_for :scores
Score
belongs_to :qa
has_one :call_component
Call Component Is just a title and description for a score
belongs_to :score
User
has_many :qas
has_many :scores, through: :qas
For whatever reason when submitting the post the scores are not created, the QA is however.
Form
<%= form_for [#qa], role: "form" do |f| %>
<%= f.label :call_id %>
<%= f.number_field :call_id, :autofocus => true, class: "form-control monospaced-control", placeholder: "Call Id", required: "" %>
... more fields
<% CallComponent.all.each do |comp| %> <!-- Usually is an array of about 5 components, so there 5 scores -->
<h4><b><%= comp.title.to_s.capitalize %></b></h4>
<p><%= comp.description.to_s.capitalize %></p>
<%= f.fields_for :scores, #qa.scores do |builder| %>
<%= builder.label :score, "Score" %>
<%= builder.number_field :score, :autofocus => true, class: "form-control monospaced-control", placeholder: "Score", required: ""%>
<%= builder.label :comments, "Comments" %><br />
<%= builder.text_area :comments, :autofocus => true, class: "form-control monospaced-control", placeholder: "Score", required: ""%>
<%= builder.hidden_field :call_component_id, :value => comp.id %>
<% end %>
<% end %>
Here is the QA New method
def new
#qa = Qa.new
#qa.scores.build
# Tried it this way too
##score = Score.new
##score.build_qa # then in the view linking the form like #score.qa, this didnt work.
end
And here is the QA Create Method
def create
#qa = Qa.new(qa_params)
#qa.final_score = #qa.scores.sum(:score).to_i
#qa.user_id = current_user.id
if #qa.save
redirect_to qas_path, notice: "New qa published!"
else
flash[:alert] = "Qa not published!"
render :new
end
end
def qa_params
params.require(:qa).permit(:call_id,...,:scores_attributes)
end
Any thoughts on how to fix this would be awesome. Thanks for your time.
try this..
def qa_params
params.require(:qa).permit(:agent_user_id, :call_id, :call_date, :case_number, :completion_date, scores_attributes: [:score,:comments,:call_component_id] )
end
as you need to specify which attributes of the nested set are permitted.
I'm really new to RoR and programming in general, and have read through a mind-numbing number of stackoverflow/railsforum/railscasts...etc. already and just can't seem to find a solution. My problem is nearly identical to this post and this post--both of which have unfortunately not been answered.
I have 3 models: Project, Task, and Assignments. I have a collection of checkboxes of existing Tasks (using simple_form and cocoon) that the user can select from, to add to a Project. Adding Tasks through checking their boxes works, but I cannot uncheck boxes and remove the association (Assignment). When I try to save my changes, I'm met with this error:
ActiveRecord::RecordNotFound in ProjectsController#update error:
Couldn't find Task with ID=28 for Project with ID=39.
def raise_nested_attributes_record_not_found!(association_name, record_id)
My guess is that AR is looking for a Task that has already been disassociated from the Project, but that's just a hunch. If that's the case, I'd still have no clue where and how to fix this problem.
Project.rb
class Project < ActiveRecord::Base
has_many :assignments, dependent: :delete_all
has_many :tasks, :through => :assignments
accepts_nested_attributes_for :tasks, reject_if: :all_blank
accepts_nested_attributes_for :assignments, :allow_destroy => true
Task.rb
class Task < ActiveRecord::Base
has_many :assignments
has_many :projects, :through => :assignments
accepts_nested_attributes_for :assignments
Assignment.rb
class Assignment < ActiveRecord::Base
belongs_to :project
belongs_to :task
accepts_nested_attributes_for :project, :reject_if => :all_blank
Project controller#update
def update
#project = Project.find(params[:id])
params[:project][:task_ids] ||= []
if #project.update_attributes(project_params)
flash[:success] = "Your project has been updated!"
redirect_to #project
else
render 'edit'
end
end
private
def project_params
params.require(:project).permit(:job_code, :task_ids => [],
tasks_attributes:
[:id, :item, :description, :requirement, :complexity,
:est_time, :actual_time, :_destroy],
assignments_attributes: [:id, :_destroy, :task_id])
end
I would greatly appreciate any help/insight/hand-holding to solve this problem! Way too much time has been spent trying to figure it out on my own, considering my limited knowledge of rails.
Thanks!
EDIT: form code included
Project edit.html.erb
<% provide(:title, "Edit project") %>
<h1>Update your project status</h1>
<div class="row">
<%= minimal_form_for #project, html: { class: "form-inline"} do |f| %>
<% if #project.errors.any? %>
<%= render 'shared/error_messages', object: f.object %>
<% end %>
<h4>Choose an existing task</h4>
<%= f.association :tasks, :collection => Task.all.to_a, :label_method => :item,
:as => :check_boxes,
:wrapper => :vertical_radio_and_checkboxes,
:checked => params[:task_id] %>
<%= render 'form', f: f %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
</div>
Project _form.html.erb
<h3>Tasks</h3>
<div id="tasks">
<%= f.simple_fields_for :tasks do |task| %>
<%= render "projects/task_fields", :f => task %>
<% end %>
<div class="links">
<%= link_to_add_association "Add task", f, :tasks, class: 'btn btn-primary' %>
</div>
</div>
Project _task_fields.html.erb
<div class="nested-fields">
<%= f.input :item %>
<%= f.input :description %>
<%= f.input :complexity, collection: Task.complexities.keys, :selected => '' %>
<%= f.input :est_time %>
<%= f.input :actual_time %>
<%= link_to_remove_association "Remove task", f, class: 'btn btn-primary' %>
</div>
You need to add a check_box named :_destroy to signal you want it deleted.
Check the guide on this matter: http://guides.rubyonrails.org/form_helpers.html#nested-forms
I need some help with handling validations with Twitter Bootstrap properly. The validations are working properly, the issue is Twitter Bootstrap Flash screen. This is what I mean:
No fields filled out and submitted returns: http://i.stack.imgur.com/8pvUc.png
The 2 of the required 4 fields submitted returns: http://i.stack.imgur.com/J6lCi.png
(notice that it doesn't flash the errors)
I have a basketball app where a Player can be on many Rosters(for player roster archiving purposes) and a Roster can have many Players.
Roster.rb
class Roster < ActiveRecord::Base
belongs_to :team
has_many :rosterizes
has_many :players, :through => :rosterizes
accepts_nested_attributes_for :players
validates_presence_of :jersey_number, :class_year
attr_accessible :jersey_number, :class_year, :players, :team_id, :players_attributes
end
Rosterizes.rb(poorly named I know...)
class Rosterize < ActiveRecord::Base
belongs_to :player
belongs_to :roster
attr_accessible :player_id, :roster_id
end
Player.rb
class Player < ActiveRecord::Base
has_many :rosterizes
has_many :rosters, :through => :rosterizes
validates_presence_of :first_name, :last_name
attr_accessible :first_name, :last_name, :active
end
_add_player_form.html.erb
(nested form)
<%= simple_nested_form_for #roster, :url =>player_added_team_path, :html => { :class => 'form-horizontal' } do |f| %>
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%end%>
<%=f.input :class_year %>
<%=f.input :jersey_number %>
<%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
<div class="well">
<%= f.button :submit, :class => 'btn-primary icon-plus-sign btn-success', :value => "Add To Team" %>
</div>
<%end%>
Thanks for the help in advance!
SOLUTION
My problem is that every time the view was loaded, it was building a new form, thus never getting back the errors on the rollback
I made a change to my controller that builds for the nested form
Controller
def add_player
...
#new_player = #roster.players.build
end
And made the change accordingly to the view
_add_player_form.html.erb
<%= f.simple_fields_for :players, #new_player do |x| %>
...
<%end%>
This did the trick, thanks Mober!
the reason why only the first level validation is shown an the associated not is fairly simple... You do a <%= f.simple_fields_for :players, #roster.players.build do |x| %> which buildes the association ALWAYS new when the sites's rendered. What you want to is building the association only if it does not exists yet...
<% #roster.players.build if !#roster.players %>
<%= f.simple_fields_for :player do |player_form| %>
...
<% end %>
Twitter Bootstrap doesn't actually validate anything, it just provides styling for validation classes (error, success, etc).
Now, I'm not a Ruby expert by any means but it looks like you are ending your form early:
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%end%> <---- here
<%=f.input :class_year %>
<%=f.input :jersey_number %>
<%=f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
Should be this?
<%= f.simple_fields_for :players, #roster.players.build do |x| %>
<%= x.input :first_name %>
<%= x.input :last_name %>
<%= x.input :active, :as => :hidden, :input_html => {:value => true} %>
<%= f.input :class_year %>
<%= f.input :jersey_number %>
<%= f.input :team_id, :as => :hidden, :input_html => {:value => params[:id]}%>
<% end %>
I have a project model that has_many :tasks. I added a nested resource in rails 3.1 and try now with the nested_form gem to be able to add/delete tasks when editing a project.
I used nested_form before in another Rails3 application and it worked fine, but now my fields_for part does not render anything.
Here is my code:
#project.rb
class Project < ActiveRecord::Base
attr_accessible :nr, :name, :client_id, :project_status_id, :hidden, :active, :description, :tasks_attributes
has_many :tasks, :dependent => :destroy
accepts_nested_attributes_for :tasks, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
end
#task.rb
class Task < ActiveRecord::Base
belongs_to :project
end
#views/projects/_form.html.erb
<%= simple_nested_form_for #project do |form| %>
<%= form.input :nr, :label => 'Nr' %>
<%= form.input :name, :label => 'Name' %>
<%= form.association :client, :collection => Client.all(:order => 'name'), :prompt => "Choose a Client" %>
<%= form.input :description, :label => 'Description' %>
<%= form.input :active, :label => 'Active' %>
<%= form.input :hidden, :label => 'Hidden' %>
<div class="task_fields">
<%= form.fields_for :tasks do |task_form| %>
<%= task_form.input :name %>
<%= task_form.input :description %>
<%= task_form.input :deadline %>
<%= task_form.link_to_remove "Remove this task" %>
<p><%= form.link_to_add "Add a task", :tasks %></p>
<% end %>
</div>
<div class="actions">
<%= form.button :submit %>
</div>
<% end %>
and in my routes:
resources :posts do
resources :comments
end
but when I visit the page in my browser the
<div class="task_fields"></div>
is rendered empty. no fields_for and whatsoever. the nested_form.js is loaded and I point in my GEMFILE to gem "nested_form", :git => 'https://github.com/fxposter/nested_form.git', as I read somewhere I need to do this in order to get simple_form support. I tried also to change simple_nested_form_for to only nested_form_for with no effect.
Any help higly appreciated
In projects#new, you have to initialize at least one task otherwise your fields_for part won't display anything.
# projects_controller.rb
def new
#project = Project.new
#project.tasks.new
end
If you want more than one task:
n.times { #project.tasks.new } # replace n with the number of tasks needed