rails validation error nested object undefined method… for nil:NilClass
up vote
0
down vote
favorite
I've made a scheduling app where people are assigned to rooms each day. On Thursdays someone must be assigned for 'pager pickup' and I'm having problems with the validation to check for that.
Model
class Schedule < ActiveRecord::Base
has_many :rooms
...
validate :thursday_schedule_must_have_pager_pickup
...
def add_rooms
return unless self.rooms.count == 0
n = 1
tomorrow = DateTime.tomorrow
Schedule.site_list.each do |site|
Schedule.const_get(site).each do |room|
self.rooms.build(order: n,
site: site.to_s,
name: room,
start_hour: get_start_hour(tomorrow),
start_minute: get_start_minute(tomorrow, site.to_s))
n += 1
end
end
self.add_pager_pickup(n, tomorrow) if true # self.for_thursday?
self.add_today_call_data(n) if no_call_data
end
...
def add_pager_pickup(order, tomorrow)
self.rooms.build(order: order,
site: "TSH",
name: "Pager Pickup",
start_hour: 7,
start_minute: get_start_minute(tomorrow, "TSH"))
end
end
class Room < ActiveRecord::Base
belongs_to :schedule
...
end
The code I'd like to write is:
def thursday_schedule_needs_pager_pickup
if self.for_thursday? && self.rooms.where(name: "Pager Pickup").first.initials.blank?
errors.add(:rooms, "'Pager Pickup' can't be empty. Select '-- late start' if no one should come in early to pick up pager.")
end
end
That generates the following errors:
NoMethodError in SchedulesController#create
undefined method `initials' for nil:NilClass
By adding the "Pager Pickup" room to the schedule last I can hack a validation with the following code:
... self.rooms.last.initials.blank?
But that's brittle and preventing me from adding a 2nd, optional, pager pickup person, "2nd Pager Pickup", after the first.
Per Julien's points:
Schedule Controller
class SchedulesController < ApplicationController
...
def new
s = current_user.schedules.new
s.add_rooms
@schedule = s
end
def create
@schedule = current_user.schedules.build(schedule_params)
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
...
end
Anyone have any thoughts?
Thanks in advance!
ruby-on-rails ruby-on-rails-4 rails-activerecord
add a comment |
up vote
0
down vote
favorite
I've made a scheduling app where people are assigned to rooms each day. On Thursdays someone must be assigned for 'pager pickup' and I'm having problems with the validation to check for that.
Model
class Schedule < ActiveRecord::Base
has_many :rooms
...
validate :thursday_schedule_must_have_pager_pickup
...
def add_rooms
return unless self.rooms.count == 0
n = 1
tomorrow = DateTime.tomorrow
Schedule.site_list.each do |site|
Schedule.const_get(site).each do |room|
self.rooms.build(order: n,
site: site.to_s,
name: room,
start_hour: get_start_hour(tomorrow),
start_minute: get_start_minute(tomorrow, site.to_s))
n += 1
end
end
self.add_pager_pickup(n, tomorrow) if true # self.for_thursday?
self.add_today_call_data(n) if no_call_data
end
...
def add_pager_pickup(order, tomorrow)
self.rooms.build(order: order,
site: "TSH",
name: "Pager Pickup",
start_hour: 7,
start_minute: get_start_minute(tomorrow, "TSH"))
end
end
class Room < ActiveRecord::Base
belongs_to :schedule
...
end
The code I'd like to write is:
def thursday_schedule_needs_pager_pickup
if self.for_thursday? && self.rooms.where(name: "Pager Pickup").first.initials.blank?
errors.add(:rooms, "'Pager Pickup' can't be empty. Select '-- late start' if no one should come in early to pick up pager.")
end
end
That generates the following errors:
NoMethodError in SchedulesController#create
undefined method `initials' for nil:NilClass
By adding the "Pager Pickup" room to the schedule last I can hack a validation with the following code:
... self.rooms.last.initials.blank?
But that's brittle and preventing me from adding a 2nd, optional, pager pickup person, "2nd Pager Pickup", after the first.
Per Julien's points:
Schedule Controller
class SchedulesController < ApplicationController
...
def new
s = current_user.schedules.new
s.add_rooms
@schedule = s
end
def create
@schedule = current_user.schedules.build(schedule_params)
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
...
end
Anyone have any thoughts?
Thanks in advance!
ruby-on-rails ruby-on-rails-4 rails-activerecord
Do you have a room record with the name Pager Pickup?
– Pavan
Nov 8 at 13:00
Good question, @Pavan. Yes, I'm pretty confident I've been careful to make sure that a typo like a spelling or case error isn't preventing a room named "Pager Pickup" from existing.
– BenU
Nov 8 at 13:04
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I've made a scheduling app where people are assigned to rooms each day. On Thursdays someone must be assigned for 'pager pickup' and I'm having problems with the validation to check for that.
Model
class Schedule < ActiveRecord::Base
has_many :rooms
...
validate :thursday_schedule_must_have_pager_pickup
...
def add_rooms
return unless self.rooms.count == 0
n = 1
tomorrow = DateTime.tomorrow
Schedule.site_list.each do |site|
Schedule.const_get(site).each do |room|
self.rooms.build(order: n,
site: site.to_s,
name: room,
start_hour: get_start_hour(tomorrow),
start_minute: get_start_minute(tomorrow, site.to_s))
n += 1
end
end
self.add_pager_pickup(n, tomorrow) if true # self.for_thursday?
self.add_today_call_data(n) if no_call_data
end
...
def add_pager_pickup(order, tomorrow)
self.rooms.build(order: order,
site: "TSH",
name: "Pager Pickup",
start_hour: 7,
start_minute: get_start_minute(tomorrow, "TSH"))
end
end
class Room < ActiveRecord::Base
belongs_to :schedule
...
end
The code I'd like to write is:
def thursday_schedule_needs_pager_pickup
if self.for_thursday? && self.rooms.where(name: "Pager Pickup").first.initials.blank?
errors.add(:rooms, "'Pager Pickup' can't be empty. Select '-- late start' if no one should come in early to pick up pager.")
end
end
That generates the following errors:
NoMethodError in SchedulesController#create
undefined method `initials' for nil:NilClass
By adding the "Pager Pickup" room to the schedule last I can hack a validation with the following code:
... self.rooms.last.initials.blank?
But that's brittle and preventing me from adding a 2nd, optional, pager pickup person, "2nd Pager Pickup", after the first.
Per Julien's points:
Schedule Controller
class SchedulesController < ApplicationController
...
def new
s = current_user.schedules.new
s.add_rooms
@schedule = s
end
def create
@schedule = current_user.schedules.build(schedule_params)
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
...
end
Anyone have any thoughts?
Thanks in advance!
ruby-on-rails ruby-on-rails-4 rails-activerecord
I've made a scheduling app where people are assigned to rooms each day. On Thursdays someone must be assigned for 'pager pickup' and I'm having problems with the validation to check for that.
Model
class Schedule < ActiveRecord::Base
has_many :rooms
...
validate :thursday_schedule_must_have_pager_pickup
...
def add_rooms
return unless self.rooms.count == 0
n = 1
tomorrow = DateTime.tomorrow
Schedule.site_list.each do |site|
Schedule.const_get(site).each do |room|
self.rooms.build(order: n,
site: site.to_s,
name: room,
start_hour: get_start_hour(tomorrow),
start_minute: get_start_minute(tomorrow, site.to_s))
n += 1
end
end
self.add_pager_pickup(n, tomorrow) if true # self.for_thursday?
self.add_today_call_data(n) if no_call_data
end
...
def add_pager_pickup(order, tomorrow)
self.rooms.build(order: order,
site: "TSH",
name: "Pager Pickup",
start_hour: 7,
start_minute: get_start_minute(tomorrow, "TSH"))
end
end
class Room < ActiveRecord::Base
belongs_to :schedule
...
end
The code I'd like to write is:
def thursday_schedule_needs_pager_pickup
if self.for_thursday? && self.rooms.where(name: "Pager Pickup").first.initials.blank?
errors.add(:rooms, "'Pager Pickup' can't be empty. Select '-- late start' if no one should come in early to pick up pager.")
end
end
That generates the following errors:
NoMethodError in SchedulesController#create
undefined method `initials' for nil:NilClass
By adding the "Pager Pickup" room to the schedule last I can hack a validation with the following code:
... self.rooms.last.initials.blank?
But that's brittle and preventing me from adding a 2nd, optional, pager pickup person, "2nd Pager Pickup", after the first.
Per Julien's points:
Schedule Controller
class SchedulesController < ApplicationController
...
def new
s = current_user.schedules.new
s.add_rooms
@schedule = s
end
def create
@schedule = current_user.schedules.build(schedule_params)
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
...
end
Anyone have any thoughts?
Thanks in advance!
ruby-on-rails ruby-on-rails-4 rails-activerecord
ruby-on-rails ruby-on-rails-4 rails-activerecord
edited Nov 10 at 12:07
asked Nov 8 at 12:56
BenU
1,6441533
1,6441533
Do you have a room record with the name Pager Pickup?
– Pavan
Nov 8 at 13:00
Good question, @Pavan. Yes, I'm pretty confident I've been careful to make sure that a typo like a spelling or case error isn't preventing a room named "Pager Pickup" from existing.
– BenU
Nov 8 at 13:04
add a comment |
Do you have a room record with the name Pager Pickup?
– Pavan
Nov 8 at 13:00
Good question, @Pavan. Yes, I'm pretty confident I've been careful to make sure that a typo like a spelling or case error isn't preventing a room named "Pager Pickup" from existing.
– BenU
Nov 8 at 13:04
Do you have a room record with the name Pager Pickup?
– Pavan
Nov 8 at 13:00
Do you have a room record with the name Pager Pickup?
– Pavan
Nov 8 at 13:00
Good question, @Pavan. Yes, I'm pretty confident I've been careful to make sure that a typo like a spelling or case error isn't preventing a room named "Pager Pickup" from existing.
– BenU
Nov 8 at 13:04
Good question, @Pavan. Yes, I'm pretty confident I've been careful to make sure that a typo like a spelling or case error isn't preventing a room named "Pager Pickup" from existing.
– BenU
Nov 8 at 13:04
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
Ok so first of all
self.rooms.where(name: "Pager Pickup")
is potentially going to return multiple objects so it doesn't give you a Room object but probably an ActiveRecord::Relation object so you would need to add something like .first before .initials to get a Room like so:
self.rooms.where(name: "Pager Pickup").first.initials.blank?
But anyway the error states that it is not finding anything so it seems that at the time of validation the rooms relationship for this schedule doesn't exist or is "empty" since it is claiming nil is returned from that query instead of an empty array so i'm guessing that your validation occurs before the room is actually created/saved.
Maybe show us the create action of the SchedulesController to see if something is wrong there.
UPDATE
After seeing your extra code, the problem is that you are calling add_rooms to a different schedule object than the one you are creating, I'm guessing your are on the impression that instance variables (variables starting with @) are persisted between requests but they are not, so the @schedule object in your create action is not the same one as in your new action therefore it doesn't have any rooms yet, update your create action to populate the rooms of that object doing something like this:
def create
@schedule = current_user.schedules.build(schedule_params)
@schedule.add_rooms # <-- Add this line
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
when isadd_roomscalled? i don't see it in thecreateaction and i'm guessing its not in theschedule_paramsso where do you call it?
– Julien
Nov 10 at 2:18
add_roomsis called in the SchedulesController#New action. I added it.
– BenU
Nov 10 at 12:14
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your@scheduleobject in thecreateaction before callingsaveon it.
– Julien
Nov 11 at 19:01
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
|
show 2 more comments
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
Ok so first of all
self.rooms.where(name: "Pager Pickup")
is potentially going to return multiple objects so it doesn't give you a Room object but probably an ActiveRecord::Relation object so you would need to add something like .first before .initials to get a Room like so:
self.rooms.where(name: "Pager Pickup").first.initials.blank?
But anyway the error states that it is not finding anything so it seems that at the time of validation the rooms relationship for this schedule doesn't exist or is "empty" since it is claiming nil is returned from that query instead of an empty array so i'm guessing that your validation occurs before the room is actually created/saved.
Maybe show us the create action of the SchedulesController to see if something is wrong there.
UPDATE
After seeing your extra code, the problem is that you are calling add_rooms to a different schedule object than the one you are creating, I'm guessing your are on the impression that instance variables (variables starting with @) are persisted between requests but they are not, so the @schedule object in your create action is not the same one as in your new action therefore it doesn't have any rooms yet, update your create action to populate the rooms of that object doing something like this:
def create
@schedule = current_user.schedules.build(schedule_params)
@schedule.add_rooms # <-- Add this line
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
when isadd_roomscalled? i don't see it in thecreateaction and i'm guessing its not in theschedule_paramsso where do you call it?
– Julien
Nov 10 at 2:18
add_roomsis called in the SchedulesController#New action. I added it.
– BenU
Nov 10 at 12:14
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your@scheduleobject in thecreateaction before callingsaveon it.
– Julien
Nov 11 at 19:01
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
|
show 2 more comments
up vote
0
down vote
Ok so first of all
self.rooms.where(name: "Pager Pickup")
is potentially going to return multiple objects so it doesn't give you a Room object but probably an ActiveRecord::Relation object so you would need to add something like .first before .initials to get a Room like so:
self.rooms.where(name: "Pager Pickup").first.initials.blank?
But anyway the error states that it is not finding anything so it seems that at the time of validation the rooms relationship for this schedule doesn't exist or is "empty" since it is claiming nil is returned from that query instead of an empty array so i'm guessing that your validation occurs before the room is actually created/saved.
Maybe show us the create action of the SchedulesController to see if something is wrong there.
UPDATE
After seeing your extra code, the problem is that you are calling add_rooms to a different schedule object than the one you are creating, I'm guessing your are on the impression that instance variables (variables starting with @) are persisted between requests but they are not, so the @schedule object in your create action is not the same one as in your new action therefore it doesn't have any rooms yet, update your create action to populate the rooms of that object doing something like this:
def create
@schedule = current_user.schedules.build(schedule_params)
@schedule.add_rooms # <-- Add this line
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
when isadd_roomscalled? i don't see it in thecreateaction and i'm guessing its not in theschedule_paramsso where do you call it?
– Julien
Nov 10 at 2:18
add_roomsis called in the SchedulesController#New action. I added it.
– BenU
Nov 10 at 12:14
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your@scheduleobject in thecreateaction before callingsaveon it.
– Julien
Nov 11 at 19:01
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
|
show 2 more comments
up vote
0
down vote
up vote
0
down vote
Ok so first of all
self.rooms.where(name: "Pager Pickup")
is potentially going to return multiple objects so it doesn't give you a Room object but probably an ActiveRecord::Relation object so you would need to add something like .first before .initials to get a Room like so:
self.rooms.where(name: "Pager Pickup").first.initials.blank?
But anyway the error states that it is not finding anything so it seems that at the time of validation the rooms relationship for this schedule doesn't exist or is "empty" since it is claiming nil is returned from that query instead of an empty array so i'm guessing that your validation occurs before the room is actually created/saved.
Maybe show us the create action of the SchedulesController to see if something is wrong there.
UPDATE
After seeing your extra code, the problem is that you are calling add_rooms to a different schedule object than the one you are creating, I'm guessing your are on the impression that instance variables (variables starting with @) are persisted between requests but they are not, so the @schedule object in your create action is not the same one as in your new action therefore it doesn't have any rooms yet, update your create action to populate the rooms of that object doing something like this:
def create
@schedule = current_user.schedules.build(schedule_params)
@schedule.add_rooms # <-- Add this line
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
Ok so first of all
self.rooms.where(name: "Pager Pickup")
is potentially going to return multiple objects so it doesn't give you a Room object but probably an ActiveRecord::Relation object so you would need to add something like .first before .initials to get a Room like so:
self.rooms.where(name: "Pager Pickup").first.initials.blank?
But anyway the error states that it is not finding anything so it seems that at the time of validation the rooms relationship for this schedule doesn't exist or is "empty" since it is claiming nil is returned from that query instead of an empty array so i'm guessing that your validation occurs before the room is actually created/saved.
Maybe show us the create action of the SchedulesController to see if something is wrong there.
UPDATE
After seeing your extra code, the problem is that you are calling add_rooms to a different schedule object than the one you are creating, I'm guessing your are on the impression that instance variables (variables starting with @) are persisted between requests but they are not, so the @schedule object in your create action is not the same one as in your new action therefore it doesn't have any rooms yet, update your create action to populate the rooms of that object doing something like this:
def create
@schedule = current_user.schedules.build(schedule_params)
@schedule.add_rooms # <-- Add this line
if @schedule.save
flash.now[:success] = "Draft Schedule Saved! Now Confirm or Edit."
render :show
else
render :new
end
edited Nov 11 at 19:18
answered Nov 8 at 22:32
Julien
8011028
8011028
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
when isadd_roomscalled? i don't see it in thecreateaction and i'm guessing its not in theschedule_paramsso where do you call it?
– Julien
Nov 10 at 2:18
add_roomsis called in the SchedulesController#New action. I added it.
– BenU
Nov 10 at 12:14
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your@scheduleobject in thecreateaction before callingsaveon it.
– Julien
Nov 11 at 19:01
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
|
show 2 more comments
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
when isadd_roomscalled? i don't see it in thecreateaction and i'm guessing its not in theschedule_paramsso where do you call it?
– Julien
Nov 10 at 2:18
add_roomsis called in the SchedulesController#New action. I added it.
– BenU
Nov 10 at 12:14
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your@scheduleobject in thecreateaction before callingsaveon it.
– Julien
Nov 11 at 19:01
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
Thanks, @Julien. Added the .first and as you predicted it still doesn't work. I edited my answer to include the SchedulesController#Create and other methods in the Schedule Model that may include my error. Thanks so much for your insight.
– BenU
Nov 9 at 14:58
when is
add_rooms called? i don't see it in the create action and i'm guessing its not in the schedule_params so where do you call it?– Julien
Nov 10 at 2:18
when is
add_rooms called? i don't see it in the create action and i'm guessing its not in the schedule_params so where do you call it?– Julien
Nov 10 at 2:18
add_rooms is called in the SchedulesController#New action. I added it.– BenU
Nov 10 at 12:14
add_rooms is called in the SchedulesController#New action. I added it.– BenU
Nov 10 at 12:14
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your
@schedule object in the create action before calling save on it.– Julien
Nov 11 at 19:01
well there's your problem, you are adding the rooms on a different schedule object than the one you are creating, you need to add the rooms to your
@schedule object in the create action before calling save on it.– Julien
Nov 11 at 19:01
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
I've edited my answer to include some details regarding my previous comment.
– Julien
Nov 11 at 19:18
|
show 2 more comments
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53208209%2frails-validation-error-nested-object-undefined-method-for-nilnilclass%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Do you have a room record with the name Pager Pickup?
– Pavan
Nov 8 at 13:00
Good question, @Pavan. Yes, I'm pretty confident I've been careful to make sure that a typo like a spelling or case error isn't preventing a room named "Pager Pickup" from existing.
– BenU
Nov 8 at 13:04