I have a scheduleevent model. The model uses ice_cube to create recurrence rules. A scheduleevent has_many schedtimeranges. A schedtimnerange has a start_time, end_time and booleans for the days of the week Sunday - Saturday. Whatever days are checked are true.
What I need to do is get those days in an array to pass them into ice_cube. How would I join scheduleevent to schedtimeranges, and get Sunday - Saturday where the value is true in a rails model? Do I query the records in the controller, then loop them in the model, or if I need to loop in the model, query them from the model?
Trying to do something like this, but getting a no method schedtimeranges error:
def self.timeranges
Schedtimeranges.where(scheduleevent_id: self.id).columns.select{ |c| c.type == :boolean }.map(&:name)
end
weekdays = self.timeranges
Scheduleevent Model:
has_many :schedtimeranges, inverse_of: :scheduleevent
accepts_nested_attributes_for :schedtimeranges, allow_destroy: true
EDIT:
weekdays = schedtimeranges.where(scheduleevent_id: id).columns.select{ |c| c.type == :boolean }.map(&:name).to_a
This works, but I just need to only get them where the value is true. How do I add that to this? So if a scheduleevent has say 3 schedtimeranges, I want to get the days of week, and start_time/end_time where they are true.
Expected output would be 07:00 AM, 14:00 PM, Monday, Thursday, Friday. (If those are the 3 days that are true.
create_table "schedtimeranges", force: :cascade do |t|
t.bigint "scheduleevent_id", null: false
t.string "start_time"
t.string "end_time"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "monday"
t.boolean "tuesday"
t.boolean "wednesday"
t.boolean "thursday"
t.boolean "friday"
t.boolean "saturday"
t.boolean "sunday"
t.index ["scheduleevent_id"], name: "index_schedtimeranges_on_scheduleevent_id"
end
EDIT 2:
This is how I am trying to create the recurrence rules. How would I loop the to_ice_cube and pass the scheduleevent_id through?
schedule = IceCube::Schedule.new(start)
case orule
when 'daily'
schedule.add_recurrence_rule IceCube::Rule.daily(1).until(end_date.to_time)
when 'weekly'
self.map(&:to_ice_cube).where(scheduleevent_id: self.id).each do |days|
schedule.add_recurrence_rule IceCube::Rule.weekly(1).day(days.map{|s| s.to_sym}).until(end_date.to_time)
end
end
The idea being that if it is a daily repeat type I just have a start time and end time between all days froms tart date to end date. If it is a weekly recurrence I want to create the rules for the times on those particular days.
I am getting an undefined method map the scheduleevent record.
CodePudding user response:
I think you made it sound way more complicated than it is. Expected output helped a lot. I've added a couple of methods to Schedtimerange
to make it simpler:
# why not ScheduleTimeRange and ScheduleEvent
class Schedtimerange < ApplicationRecord
# sometimes you just have to type all the attributes that you need
def days
{
monday: monday,
tuesday: tuesday,
wednesday: wednesday,
thursday: thursday,
friday: friday,
saturday: saturday,
sunday: sunday
}
end
# # or like this
# DAYS = %w[monday tuesday wednesday thursday friday saturday sunday].freeze
# def days
# attributes.slice(*DAYS)
# end
# desired format goes here
def to_ice_cube
[start_time, end_time, *days.compact_blank.keys]
end
end
https://api.rubyonrails.org/classes/Hash.html#method-i-compact_blank-21
>> Schedtimerange.first.to_ice_cube
=> ["07:00 AM", "08:00 AM", :monday, :friday]
>> Schedtimerange.where(scheduleevent_id: 1).map(&:to_ice_cube)
=> [["07:00 AM", "08:00 AM", :monday, :friday], ["11:00 AM", "04:00 PM", :monday, :tuesday]]
Do the same for Scheduleevent
if you want:
class Scheduleevent < ApplicationRecord
has_many :schedtimeranges
def to_ice_cube
[id, schedtimeranges.map(&:to_ice_cube)]
end
end
>> Scheduleevent.limit(2).map(&:to_ice_cube)
=> [[1, [["07:00 AM", "08:00 AM", :monday, :friday], ["11:00 AM", "04:00 PM", :monday, :tuesday]]],
[2, [[nil, nil, :monday, :tuesday], [nil, nil, :tuesday, :wednesday]]]]
If you're calling it from Scheduleevent
, just use association to get relevant ranges:
schedtimeranges.map(&:to_ice_cube).each do |days|
schedule.add_recurrence_rule IceCube::Rule.weekly(1).day(days).until(end_date.to_time)
end