Cannot submit Checkbox through nested form - ruby-on-rails

Im trying to create an application were teachers a able to select students each day who aren't in school. I created the models through nifty-generators gem. The problem is that it wont submit to the notpresents table. Please help.
# == Schema Information
#
# Table name: students
#
# id :integer not null, primary key
# name :string(255)
# group_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Student < ActiveRecord::Base
attr_accessible :name, :group_id
belongs_to :days
end
# == Schema Information
#
# Table name: notpresents
#
# id :integer not null, primary key
# student_id :integer
# day_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Notpresent < ActiveRecord::Base
attr_accessible :student_id, :day_id
belongs_to :days
end
# == Schema Information
#
# Table name: days
#
# id :integer not null, primary key
# title :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class Day < ActiveRecord::Base
attr_accessible :title, :presents
has_many :notpresents
accepts_nested_attributes_for :notpresents
end
And view _form.html.erb
<%= form_for #day do |f| %>
<%= f.error_messages %>
<p>
<%= f.label :title %><br />
<%= f.text_field :title %>
</p>
<% for student in Student.find(:all) %>
<div>
<%= check_box_tag :notpresents, student.id%>
<%= student.name %>
</div>
<% end %>
<p><%= f.submit %></p>
<% end %>

I've never used the nifty-generators gem, but if a student can be absent in many days, and a day can have many students absent, shouldn't you have a many-to-many relationship?
class Student < ActiveRecord::Base
attr_accessible :name
has_many :days, through: :notpresents
has_many :notpresent
end
class Days < ActiveRecord::Base
attr_accessible :date
has_many :students, through: :notpresents
has_many :notpresent
end
class :Notpresents < ActiveRecord::Base
attr_accessible :student_id, :day_id
belongs_to :students
belongs_to :days
end
It could also be a has_and_belongs_to_many association, but with a has_many :through you could have a string or text attribute to make a note about the absence or something like that.
I recommend using simple_form for the form, it makes it so easy:
app/controllers/days_controller.rb:
def edit
#day = Day.find(params[:id])
end
app/views/days/_form.html.erb :
<%= simple_form_for #day do |f| %>
<%= f.association :students, as: :check_boxes %>
<% end %>

Related

Validation failed: Park must exist, User must exist

I'm working on a project where Users can see dog Parks and make individual Playdates for each park. The issue I'm having is that the PlaydatesController create action is not persisting the user_id and park_id that each new playdate is associated with. I've tried adding optional: true to my Playdate model, which does save each playdate. However, doing this makes a null column entry for the user_id and park_id.
All I need is the user_id and park_id to create a playdate and keep the association between playdates and parks... Did I mess up my associations? Any help is GREATLY appreciated.
Here's my code:
Playdate MODEL:
class Playdate < ApplicationRecord
belongs_to :park
belongs_to :user
validates :date, presence: true
validates :time, presence: true
end
Park MODEL:
class Park < ApplicationRecord
has_many :playdates
has_many :comments
has_many :users, through: :comments
end
User MODEL:
class User < ApplicationRecord
has_many :parks
has_many :playdates
has_many :comments, through: :parks
end
Playdates CONTROLLER:
def create
#playdate = Playdate.new(playdate_params)
if #playdate.save!
redirect_to park_path(#park)
else
render :new
end
end
private
def playdate_params
params.require(:playdate).permit(:time, :date, :user_id, :park_id)
end
Playdates NEW VIEW:
<%= form_for #playdate do |f| %>
<%= f.label :date %>
<%= f.date_field :date %><br><br>
<%= f.label :time %>
<%= f.time_field :time %><br><br>
<%= hidden_field_tag :user_id, current_user.id %>
<%= hidden_field_tag :park_id, #park%>
<%= f.submit "Add Playdate!" %>
<% end %>
You should use:
f.hidden_field :user_id, value: current_user.id
f.hidden_field :park_id, value: #park.id
The rendered HTML is not the same between "hidden_field_tag" and "hidden_field". Try by yourself to see the difference.

Rails form multiple checkboxes for associated model

I'm creating an application where a "submission" can be made using a form which creates client details and allows "referrals" to be created depending on the branch(es) that can provide the required service
class Submission < ActiveRecord::Base
has_many :referrals, :inverse_of => :submission, dependent: :delete_all
accepts_nested_attributes_for :referrals, :allow_destroy => true
end
class Referral < ActiveRecord::Base
belongs_to :submission
end
class Branch < ActiveRecord::Base
has_many :referrals
end
Submissions controller:
def new
#submission = Submission.new
#submission.build_client
#submission.client.build_address
#submission.referrals.build
end
def submission_params
params.require(:submission).permit(:consent, :user_id, client_attributes:
[:client_id, :first_name,
address_attributes:
[:first_line, :second_line,]
],
referrals_attributes:
[:branch_id]
)
end
The Submission form:
<%= form_for(#submission) do |f| %>
<%= f.fields_for :referrals do |referral| %>
<%= render 'referral_fields', f: referral %>
<% end %>
<% end %>
_referral_fields.html.erb:
<% Branch.all.where(referrable: true).each do |branch| %>
<label>
<%= check_box_tag 'branch_ids[]', branch.id %>
<%= branch.name %>
</label>
<% end %>
What I want is to have checkboxes for each referrable branch. When a branch is ticked and the submission is created, a referral will be created for that branch. However, when I submit the form, I get a validation error of "Referrals can't be blank". Any idea why this is not working?
Any help is most appreciated
Use collection_check_boxes.
<% # _referral_fields.html.erb %>
<%= f.collection_check_boxes(:branch_ids, Branch.where(referrable: true), :id, :name) do |b|
b.label { b.check_box } # wraps check box in label
end %>
You would need to whitelist submission[referrals_attributes][branch_ids] - not branch_id.
def submission_params
params.require(:submission)
.permit(
:consent,
:user_id,
client_attributes: [
:client_id,
:first_name,
address_attributes: [
:first_line, :second_line,
]
],
referrals_attributes: [:branch_ids]
)
end
Edited.
However for this to work you need to setup a relation between Referral and Branch. In this case you could use either a has_and_belongs_to_many (HABTM) or has_many though: (HMT) relationship.
See Choosing Between has_many :through and has_and_belongs_to_many.
class Referral < ActiveRecord::Base
belongs_to :submission
has_and_belongs_to_many :branches
end
class Branch < ActiveRecord::Base
has_and_belongs_to_many :referrals
end
You need to create a join table as well:
rails g migration CreateBranchReferralJoinTable branch referral

how to get the reference?

please help solve the problem.
There is a table users:
id :integer, autoincrement
name :string
gender_id :integer
There is a table genders:
id :integer, autoincrement
gender_name :string
model User:
class User < ActiveRecord::Base
belongs_to :gender
end
model Gender:
class Gender < ActiveRecord::Base
has_many :users
end
I need the gendername. I try to do so:
<% #users.each do |user| %>
<div class="col-xs-6"><%= user.name %></div>
<div class="col-xs-2"><%= user.gender_id %></div>
<% end %>
the result is output number, but I need to gendername
my column 'gender_id' contain zero value. This problem has been

Rails multiple Has_one relationship to same model

I am working on a Rails application and currently I have 2 models - Subjects and Lessons.
A Subject has 3 different types of lessons - Lecture, Tutorial and Laboratory. I modelled such that there are 3 has_one to the Lesson model.
Right now, I am trying to create a nested form for subjects and lessons but the lecture, tutorial and laboratory being saved was always the first form that was rendered.
i.e. I have 3 nested forms separately for Lecture, Tutorial and Laboratory but the Lecture, Tutorial and Laboratory that was saved was always the one that was first built. In my codes the lecture was first built so the attributes for tutorial and laboratory would follow the one that I have filled in for my lecture.
I am not sure where I have went wrong or even if having multiple has_one relationship works in this case so any advice would be appreciated.
The related codes are as follows:
The subject model
class Subject < ActiveRecord::Base
has_one :lecture, :class_name => "Lesson"
has_one :laboratory,:class_name => "Lesson"
has_one :tutorial, :class_name => "Lesson"
accepts_nested_attributes_for :lecture
accepts_nested_attributes_for :laboratory
accepts_nested_attributes_for :tutorial
end
The lesson model
class Lesson < ActiveRecord::Base
belongs_to :subject
end
The Subject and lesson nested form
<%= form_for(#subject_list) do |f| %>
<div class="field">
<%= f.label :subject_code %><br />
<%= f.text_field :subject_code %>
</div>
<div>
<%= f.fields_for :lecture do |lecture| %>
<%= render "lecture_fields", :f => lecture %>
<% end %>
</div>
<div>
<%= f.fields_for :tutorial do |tutorial| %>
<%= render "tutorial_fields", :f => tutorial %>
<% end %>
</div>
<div>
<%= f.fields_for :laboratory do |laboratory| %>
<%= render "laboratory_fields", :f => laboratory %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The new action in the subject controller
def new
#subject = Subject.new
lecture = #subject.build_lecture
laboratory = #subject.build_laboratory
tutorial = #subject.build_tutorial
respond_to do |format|
format.html # new.html.erb
format.json { render json: #subject }
end
end
I would appreciate if someone could help me out in identifying where I have went wrong. If in the case that I should not be creating such multiple relationships, I would like to have some advice on how could I actually render out 3 forms with a default field indicating the lesson type.
I'm not really sure if that works, but my advise is to use AR inheritance
class Lesson < ActiveRecord::Base
end
class LectureLesson < Lesson
belongs_to :subject
end
class LaboratyLesson < Lesson
belongs_to :subject
end
class TutorialLesson < Lesson
belongs_to :subject
end
class Subject
has_one :lecture_lesson
has_one :laboratory_lesson
has_one :tutorial_lesson
accepts_nested_attributes_for :lecture_lesson
accepts_nested_attributes_for :laboratory_lesson
accepts_nested_attributes_for :tutorial_lesson
end
Migration
class LessonsAndSubjects < ActiveRecord::Migration
def up
remove_column :subjects, :lesson_id
add_column :subjects, :lecture_lesson_id, :integer
add_column :subjects, :laboratory_lesson_id, :integer
add_column :subjects, :tutorial_lesson_id, :integer
add_column :lessons, :type, :string
add_index :subjects, :lecture_lesson_id
add_index :subjects, :laboratory_lesson_id
add_index :subjects, :tutorial_lesson_id
end
def down
remove_column :subjects, :lecture_lesson_id
remove_column :subjects, :laboratory_lesson_id
remove_column :subjects, :tutorial_lesson_id
remove_column :lessons, :type
add_column :subjects, :lesson_id, :integer
end
end
it makes more sense and it may be fix you issue with nested attributes
Actually from the answer from rorra one point is missing, you need to add a polymorphic association for each "children" to not incurr in query problems
class Lesson < ActiveRecord::Base
belongs_to :subject
end
class LectureLesson < Lesson
belongs_to :polymorphic_lecture_lesson, polymorphic: true
end
class Subject
has_one :lesson
has_one :lecture_lesson, as: :polymorphic_lecture_lesson
accepts_nested_attributes_for :lesson
accepts_nested_attributes_for :lecture_lesson
end
in migration you have then to add
add_column :lessons, :polymorphic_lecture_lesson_id, :integer, index: true
add_column :lessons, :polymorphic_lecture_lesson_type, :integer, index: true
Interestingly, I interpreted this question much differently than the other answers seem to have.
If you are looking to have 2 has_one to a single model/table, then one can do the following:
Given a Person has one best pet and one worst pet, which are represented by the same Pet table/model that has an attribute to differentiate between the two...
class Person < ApplicationRecord
has_one :best_pet, -> { where(pet_type: "best") }, class_name: "Pet"
has_one :worst_pet, -> { where(pet_type: "worst") }, class_name: "Pet"
...
end
class Pet < ApplicationRecord
belongs_to :person
validates_presence_of :pet_type
validates_uniqueness_of :pet_type, scope: :person_id
...
end
Now, whether or not this is good database design is up for debate.

"Can't mass-assign protected attributes" with nested protected models

I'm having a time trying to get this nested model working. I've tried all manner of pluralization/singular, removing the attr_accessible altogether, and who knows what else.
restaurant.rb:
# == RESTAURANT MODEL
#
# Table name: restaurants
#
# id :integer not null, primary key
# name :string(255)
# created_at :datetime not null
# updated_at :datetime not null
#
class Restaurant < ActiveRecord::Base
attr_accessible :name, :job_attributes
has_many :jobs
has_many :users, :through => :jobs
has_many :positions
accepts_nested_attributes_for :jobs, :allow_destroy => true
validates :name, presence: true
end
job.rb:
# == JOB MODEL
#
# Table name: jobs
#
# id :integer not null, primary key
# restaurant_id :integer
# shortname :string(255)
# user_id :integer
# created_at :datetime not null
# updated_at :datetime not null
#
class Job < ActiveRecord::Base
attr_accessible :restaurant_id, :shortname, :user_id
belongs_to :user
belongs_to :restaurant
has_many :shifts
validates :name, presence: false
end
restaurants_controller.rb:
class RestaurantsController < ApplicationController
before_filter :logged_in, only: [:new_restaurant]
def new
#restaurant = Restaurant.new
#user = current_user
end
def create
#restaurant = Restaurant.new(params[:restaurant])
if #restaurant.save
flash[:success] = "Restaurant created."
redirect_to welcome_path
end
end
end
new.html.erb:
<% provide(:title, 'Restaurant') %>
<%= form_for #restaurant do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label "Restaurant Name" %>
<%= f.text_field :name %>
<%= f.fields_for :job do |child_f| %>
<%= child_f.label "Nickname" %>
<%= child_f.text_field :shortname %>
<% end %>
<%= f.submit "Done", class: "btn btn-large btn-primary" %>
<% end %>
Output Parameters:
{"utf8"=>"✓",
"authenticity_token"=>"DjYvwkJeUhO06ds7bqshHsctS1M/Dth08rLlP2yQ7O0=",
"restaurant"=>{"name"=>"The Pink Door",
"job"=>{"shortname"=>"PD"}},
"commit"=>"Done"}
The error i'm receiving is:
ActiveModel::MassAssignmentSecurity::Error in RestaurantsController#create
Cant mass-assign protected attributes: job
Rails.root: /home/johnnyfive/Dropbox/Projects/sa
Application Trace | Framework Trace | Full Trace
app/controllers/restaurants_controller.rb:11:in `new'
app/controllers/restaurants_controller.rb:11:in `create'
Anyone have ANY clue how to get this to work? Thanks!
in restaurant.rb:
it should be
attr_accessible :name, :jobs_attributes
instead of
attr_accessible :name, :job_attributes
regarding your last comment:
you can submit the user_id within your job form, that should submit the user_id to the model

Resources