Rails simple_form association with nested form - ruby-on-rails

My application has 3 models : consultant, project and appointment
I am using a nested form with simple_form gem
class Consultant < ActiveRecord::Base
has_many :appointments
end
class Project < ActiveRecord::Base
has_many :appointments, :dependent => :destroy
accepts_nested_attributes_for :appointments, :allow_destroy => true
end
class Appointment < ActiveRecord::Base
belongs_to :consultant
belongs_to :project
end
My form is as follows :
= simple_nested_form_for(#project) do |f|
%div.field
= f.input :name, :label => 'Nom du projet'
= f.simple_fields_for :appointments do |builder|
= render 'appointment_fields', :f => builder
= f.link_to_add "ajouter un consultant", :appointments
%div
%div.actions
= f.submit
with the partial :
%p.fields
= f.input :consultant_id, :input_html => { :class => 'special' }
= f.association :consultant
= f.input :nb_days, :input_html => { :class => 'special',:size => 10 }
= f.input :rate, :input_html => {:size => 10}
= f.link_to_remove "Remove this task"
Is it possible to do something as simple as this with simple_form ?
The answer is YES : it works nicely

The errors is because there is no association called consultant on the model Appointment. Use consultants instead.

Related

Rails has_one relationship and simple_form

Using simple_form to build a nested form for a WorkoutSet model with the following fields:
intro_video
get_ready
outro_video
WorkoutStep (another nested model)
I want to be able to select an intro_video out of a select
As WorkoutSet is inside Workout, the forms look like this:
WorkoutSet.rb
class WorkoutSet < ActiveRecord::Base
has_and_belongs_to_many :workout_steps, :join_table => :sets_steps, dependent: :destroy
has_and_belongs_to_many :workouts, :join_table => :workout_sessions
accepts_nested_attributes_for :workout_steps, allow_destroy: true
has_one :intro_video_usage, class_name: 'VideoUsage::Intro', as: :parent, dependent: :destroy
has_one :intro_video, through: :intro_video_usage, source: :video
accepts_nested_attributes_for :intro_video
has_one :get_ready_video_usage, class_name: 'VideoUsage::GetReady', as: :parent, dependent: :destroy
has_one :get_ready_video, through: :get_ready_video_usage, source: :video
has_one :congrats_video_usage, class_name: 'VideoUsage::Congratulations', as: :parent, dependent: :destroy
has_one :congrats_video, through: :congrats_video_usage, source: :video
end
_form.html.haml
%h2 Sets
.sets.some{ :style => "margin-left: 25px" }
= f.simple_fields_for :workout_sets do |set|
= render 'workout_set_fields', f: set
.links
.button-row
= link_to_add_association 'add set', f, :workout_sets
_workout_set_fields.html.haml
.nested-fields
%h2 New set - #{link_to_remove_association 'Delete', f}
= f.label :title
= f.text_field :title
= f.input :intro_video, :collection => Video.all, :label_method => :title, :value_method => :id, :include_blank => false
%br
%br
#sets.some{ :style => "margin-left: 25px" }
= f.simple_fields_for :workout_steps do |step|
= render 'workout_step_fields', f: step
.links
.button-row
= link_to_add_association 'add step', f, :workout_steps
The select is rendered and the values looks fine until I save the model whitelisting the following parameters:
params.require(:workout).permit(:title, :pro, :image, warmup_attributes: [:id, :_destroy, {main_video_ids: []}], workout_sets_attributes: [:id, :_destroy, :title, :intro_video, workout_steps_attributes: [:id, :_destroy, {main_video_ids: []}] ])
Also, I notice that in the line f.input :intro_video the parameter being sent is intro_video, instead of intro_video_attributes
Thanks in advance.

ActiveAdmin ::Show 4 textbox in active admin using has_many relationship

I have one poll table having with question filed and each question have 4 answer which is has_many relation ship with answer table
class Poll < ActiveRecord::Base
has_many :answer
end
My answer model
class Answer < ActiveRecord::Base
belongs_to :poll, :class_name => "Poll", :foreign_key => "question_id"
end
My active admin form is
form :html => {:validate => true} do |f|
f.inputs "Polls" do
f.input :question
f.has_many :answer, :sortable => :priority do |ff|
ff.input :question[]
end
f.input :status,as: 'hidden',:input_html => { :value => f.object.status.present? ? f.object.status : 'Unpublished' }
f.input :position,as: 'hidden',:input_html => { :value => Poll.count().to_i + 1}
end
f.actions
end
I want to show only 4 answer textbox into my form, how can i do that
Add the following to your Polls Controller-
def new
#poll = Poll.new
4.times do
#poll.answers.build
end
end

Activeadmin formtastic dynamic select

I would like to make a dynamic select option via Activeadmin's formtastic like so:
form do |f|
f.inputs "Exam Registration Details" do
f.input :user_id, :as => :select, :collection => User.where(:admin => 'false')
#selects user from list. WORKING
f.input :student_id, :as => :select, :collection => Student.joins(lessons: :user)
#collection of students will change to students who have lessons with chosen user. NOT WORKING, returns all students who have lessons.
f.input :lesson_id, :as => :select, :collection => Lesson.joins(:student, :user)
#collection of lessons will change to reflect lessons connected by chosen user and student. NOT WORKING, returns all lessons.
end
f.buttons
end
My amateurish code is obviously not working as I intended it to. What changes should I make?
I have 4 models as below:
class Student < ActiveRecord::Base
has_many :lessons
has_many :users, through: :lessons
has_many :exam_registrations, through: :lessons
class Lesson < ActiveRecord::Base
belongs_to :user
belongs_to :student
belongs_to :exam_registration
class User < ActiveRecord::Base
has_many :lessons
has_many :students, through: :lessons
has_many :exam_registrations, through: :lessons
class ExamRegistration < ActiveRecord::Base
has_many :lessons
has_many :users, through: :lessons
has_many :students, through: :lessons
SOLVED
For anyone else wrestling with the same problem, look at this railscast
here's how I implemented multiple dynamic select menus in activeadmin:
config/initializers/active_admin.rb
config.register_javascript 'exam_registrations.js.coffee'
app/admin/exam_registrations.rb
form do |f|
f.inputs "Exam Registration Details" do
f.input :user_id, :label => 'Teacher', :as => :select, :collection => User.where(:admin => 'false', :active => true).order(:name), :include_blank => true
f.input :student_id, :hint => 'Students grouped by teacher names', :as => :select, :collection => option_groups_from_collection_for_select(User.where(:admin => false, :active => true).order(:name), :students, :name, :id, :name)
f.input :lesson_id, :hint => 'Lessons grouped by student names', :as => :select, :collection => option_groups_from_collection_for_select(Student.where(:active => true).order(:name), :lessons, :name, :id, :name)
end
f.buttons
end
app/assets/javascripts/exam_registrations.js.coffee
#first menu
jQuery ->
$('#exam_registration_student_id').parent().hide()
students = $('#exam_registration_student_id').html()
$('#exam_registration_user_id').change ->
user = $('#exam_registration_user_id :selected').text()
escaped_user = user.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(students).filter("optgroup[label='#{escaped_user}']").html()
if options
$('#exam_registration_student_id').html(options)
$('#exam_registration_student_id').parent().show()
else
$('#exam_registration_student_id').empty()
$('#exam_registration_lesson_id').empty()
# second menu
$('#exam_registration_lesson_id').parent().hide()
lessons = $('#exam_registration_lesson_id').html()
$('#exam_registration_student_id').click ->
student = $('#exam_registration_student_id :selected').text()
escaped_student = student.replace(/([ #;&,.+*~\':"!^$[\]()=>|\/#])/g, '\\$1')
options = $(lessons).filter("optgroup[label='#{escaped_student}']").html()
if options
$('#exam_registration_lesson_id').html(options)
$('#exam_registration_lesson_id').parent().show()
else
$('#exam_registration_lesson_id').empty()
restart the server and the menus work!

Rails has_many :through and collection_select with multiple

I have the following problem using a has_many :through many-to-many relation in a multi-select via collection_select :multiple => true. I have Suppliers who deliver many Ingredients which can be delivered by many Suppliers. Have a look:
The Ingredient model:
class Ingredient < ActiveRecord::Base
has_many :ingredient_suppliers
accepts_nested_attributes_for :ingredient_suppliers, :allow_destroy => true
has_many :suppliers, :through => :ingredient_suppliers
end
The Supplier model:
class Supplier < ActiveRecord::Base
has_many :ingredient_suppliers
has_many :ingredients, :through => :ingredient_suppliers
end
The relationship Entity:
class IngredientSupplier < ActiveRecord::Base
belongs_to :ingredient
belongs_to :supplier
end
And this is the form. Note that I could not get it to work without specifying the :name:
<%= form_for(#ingredient) do |f| %>
<%= f.fields_for :suppliers do |supplier_fields| %>
<%= supplier_fields.collection_select (:supplier_ids,
Supplier.all(:order=>"name ASC"),
:id, :name,
{:selected => #ingredient.supplier_ids,
:include_blank => true},
{:multiple => true,
:name => 'ingredient[supplier_ids]'}) %>
<% end %>
<% end %>
If I remove the :name, then I get this error message:
Supplier(#-617951108) expected, got Array(#-608411888)
Request
Parameters:
{"commit"=>"Anlegen",
"authenticity_token"=>"MuEYtngwThharmM1KaAbH8JD3bScXiDwj0ALMytxl7U=",
"_method"=>"put",
"utf8"=>"✓",
"id"=>"1",
"ingredient"=>{"name"=>"Ingredient 1",
"nr"=>"00100",
"unit"=>"kg",
"mol_per_unit"=>"2000,
00000",
"description"=>"",
"suppliers"=>{"supplier_ids"=>["1",
"2"]}}}
The problem now is, that the PUT parameters only contain one supplier_id instead of an array of supplier_ids:
"ingredient"=>{"name"=>"Rohstoff 3", "nr"=>"00300", "unit"=>"Stk.", "mol_per_unit"=>"0,00000", "description"=>"", "supplier_ids"=>"2"}
I've got the problem solved. In this case, using fields_for was the error. The solution is using a collection_select, like this:
<%= collection_select(:ingredient, :supplier_ids,
Supplier.all(:order=>"name ASC"),
:id, :name, {:selected => #ingredient.supplier_ids, :include_blank => true}, {:multiple => true}) %>

Rails nested model with formtastic is skipping one field?

I have this structure models
class Tournament < ActiveRecord::Base
AGES = ["5u", "6u", "7u", "8u"]
has_many :courts, :dependent => :destroy
accepts_nested_attributes_for :courts, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
class Court < ActiveRecord::Base
belongs_to :tournament, :autosave => true
has_many :ages, :dependent => :destroy
accepts_nested_attributes_for :ages, :reject_if => lambda { |a| a[:name].blank? }, :allow_destroy => true
class Age < ActiveRecord::Base
belongs_to :court
Now my forms look like this
_form.html.erb
<%= semantic_form_for #tournament do |f| %>
<%= f.inputs do %>
<%= f.input :name, :hint => "What is the name of the Tournament?" %>
<%= f.semantic_fields_for :courts do |builder| %>
<%= render :partial => "court_fields", :locals => { :f => builder } %>
<% end %>
_court_fields.html.erb
<div class="nested_fields">
<%= f.input :name, :input_html => {:class => "name"} %>
<%= f.semantic_fields_for :ages do |builder| %>
<%= render :partial => "age_fields", :locals => { :f => builder } %>
<% end %>
_age_fields.html.erb
Testing ...am I getting in here
<%= f.input :name, :as => :check_boxes, :collection => Tournament::AGES, :input_html => {:class => "age_limits"} %>
everything seems to work well except nothing shows up in the ages_fields partial...not the checkboxes and not even the dummy text Testing ...am I getting in here is not displaying....any ideas what could be causing the issue
The obvious reason I can think of: are you sure your Court has ages ?
[EDIT] That the Court has the relation was indeed clear to me.
But your code will only show an age for a court if it already exists.
From your output in the comments: the court has no actual ages so no ages are shown.
If you do this in your controller:
def new
#tournament = Tournament.new
#tournament.courts.build
#tournament.courts[0].ages.build
end
This will make sure that you have at least one (empty) court and one (empty) age.
Otherwise you could also consider using a gem like cocoon to dynamically add new elements if needed.
Hope this helps.

Resources