Compare an array of dates to one day (in a rails calendar) - ice-cube

I'm using the calendar helper from Railscast: http://railscasts.com/episodes/213-calendars-revised but I'm running into a problem (calendar helper below):
module CalendarHelper
def calendar(date = Date.today, &block)
Calendar.new(self, date, start_date, end_date, scheduled, block).table
end
class Calendar < Struct.new(:view, :date, :start_date, :end_date, :scheduled, :callback)
HEADER = %w[S M T W T F S]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
weeks.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "start_date" if day == start_date
classes << "end_date" if day == end_date
classes << "notmonth" if day.month != date.month
classes << "scheduled" if day == scheduled
classes.empty? ? nil : classes.join(" ")
end
def weeks
first = date.beginning_of_month.beginning_of_week(START_DAY)
last = date.end_of_month.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
end
My application spits out an array of scheduled dates (using the ice_cube gem). For each one of those dates I want to match them with dates from the calendar, assigning them with the class "scheduled". I can't figure out how to do this. This code is what I'm trying to make work:
classes << "scheduled" if day == scheduled
'scheduled' comes from the controller:
Application_Controller.rb
def scheduled
Schedule.find(params[:id]).itinerary.all_occurrences if params[:id]
end
helper_method :scheduled
Which returns the following array of dates:
=> [2014-05-16 00:00:00 -0400, 2014-05-19 00:00:00 -0400, 2014-05-20 00:00:00 -0400, 2014-05-21 00:00:00 -0400, 2014-05-22 00:00:00 -0400, 2014-05-23 00:00:00 -0400, 2014-05-26 00:00:00 -0400, 2014-05-27 00:00:00 -0400, 2014-05-28 00:00:00 -0400, 2014-05-29 00:00:00 -0400]
I've tried a number of scenarios but I can't figure it out.
As an example, this will work and show the "scheduled" class for these 3 days but I can't figure out how to loop through all the scheduled dates and still have an || operator in the block:
def day_classes(day)
...
classes << "scheduled" if Date.yesterday == day || Date.tomorrow == day || Date.today == day
...
end
Or maybe someone has a better idea?

After a bit of reading through the ice_cube gem I found a handy method that does exactly what I needed.
def day_classes(day)
...
classes << "scheduled" if scheduled.itinerary.occurs_on?(day)
...
end

Related

undefined method when trying to get the first day of the week - Rails 5

I'm making a calendar, I'm trying to get the first day of the week, as well as the last day of the week. When trying to do this, I get an error in /lib/calencar.rb:
undefined method `beginning_of_month 'for {: date => Wed, 23 Jan 2019}: Hash
This is the code calendar.rb
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar table table-bordered table-striped" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
weeks.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "not-month" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
def weeks
#first = DateTime.strptime(date, "%B %d, %Y")
first = date.beginning_of_month.beginning_of_week(START_DAY)
last = date.end_of_month.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
Also, in the index#index controller I have the following code:
class IndexController < ApplicationController
helper CalendarHelper
def index
#date = params[:date] ? Date.parse(params[:date]) : Date.today
end
end
Thank you
undefined method `beginning_of_month 'for {: date => Wed, 23 Jan 2019}: Hash
You are trying to use a beginning_of_month method on a Hash not on a DateTime object, check the assignment of your date variable.

Filtering by created_at (start_datetime and end_datetime) picks only one date which is end_datetime

I am trying to create a filter for my revenue_controller show action, but its not working very well.
This is what I have done in the code below, but it picks the end_datetime alone when I filter by date.
revenue_controller.rb
What am trying to do in the show action is default my search to 30days from now, and if params filled with date, use the selected datetime.
module Admin
module Statistic
class RevenuesController < BaseController
def show
#revenues_reports = Currency.all.map do |currency|
puts params
start_datetime = if params[:created_at].nil? then
30.days.ago
else
params[:created_at].slice(0..15)
end
end_datetime = if params[:created_at].nil? then
Time.now
else
params[:created_at].slice(0..15)
end
get_revenue_report_for_currency(currency, start_datetime, end_datetime)
end
end
def get_revenue_report_for_currency(currency, start_datetime, end_datetime)
puts "start: #{start_datetime}" # I added this to see from the log the start_datetime it picks
puts "end: #{end_datetime}" # I added this to see from the log the end_datetime it picks
total_withdraw_fees_charged = Withdraw.where(:currency => currency.id, :created_at => start_datetime..end_datetime).sum(:fee)
total_withdraw_network_fees_charged = 0.3 * total_withdraw_fees_charged
net_income_from_withdraws = total_withdraw_fees_charged - total_withdraw_network_fees_charged
total_sell_order_fees_charged = Order.where(:type => 'OrderAsk', :bid => currency.id, :created_at => start_datetime..end_datetime).sum(:fee)
total_buy_order_fees_charged = Order.where(:type => 'OrderBid', :ask => currency.id, :created_at => start_datetime..end_datetime).sum(:fee)
total_trading_fees = total_sell_order_fees_charged + total_buy_order_fees_charged
total_fees = net_income_from_withdraws + total_trading_fees
{
currency: currency.code.upcase,
total_withdraw_fees_charged: total_withdraw_fees_charged,
total_withdraw_network_fees_charged: total_withdraw_network_fees_charged,
net_income_from_withdraws: net_income_from_withdraws,
total_sell_order_fees_charged: total_sell_order_fees_charged,
total_buy_order_fees_charged: total_buy_order_fees_charged,
total_trading_fees: total_trading_fees,
total_fees: total_fees
}
end
end
end
end
show.html.erb
.panel.panel-primary
.panel-heading
h4.panel-title = t('admin.statistic.filter')
.panel-body
= form_tag(admin_statistic_revenue_path, :method => 'get', class: 'form-horizontal') do |f|
.row
.col.col-xs-3
label[for="#"]
| Start Date:
input.form-control.created_at.date_time_filter.from[name="[created_at]" type="#" value=""]
.col.col-xs-3
label[for="#"]
| End Date:
input.form-control.created_at.date_time_filter.to[name="[created_at]" type="#" value=""]
= button_tag "Search", :class => 'btn btn-info', :name => nil
browser params url
http://localhost:3000/admin/statistic/revenue?utf8=%E2%9C%93&%5Bcreated_at%5D=2018-08-01+00%3A00&%5Bcreated_at%5D=2018-10-05+00%3A00
development_logs
You are trying to use single parameter name for two different parameters created_at_from and created_at_to:
.col.col-xs-3
label[for="#"]
| Start Date:
input.form-control.created_at.date_time_filter.from[name="created_at_from" type="#" value=""]
.col.col-xs-3
label[for="#"]
| End Date:
input.form-control.created_at.date_time_filter.to[name="created_at_to" type="#" value=""]
created_at is usually datetime, so will have non-zero time for most records.
And 2018-10-05 12:34:56 +0100 is greater than 2018-10-05 00:00:00.
Correct filter for 'records created at specific date' is 'records created after that day has started, but before and of day':
start_datetime = if params[:created_at_from].present?
Time.zone.parse(params[:created_at_from]).beginning_of_day
else
30.days.ago
end
end_datetime = if params[:created_at_to].present?
Time.zone.parse(params[:created_at_to]).end_of_day
else
Time.zone.now
end
Also note zone, because depending on timezone day may start in different universal time.

a Struck constant won't allow me to create a calendar

I am trying to create a calendar and have been following a tutorial on YouTube calendar ruby on rails first video. once I inputted the code I had an error,
uninitialized constant CalenderHelper::Struck
the code is;
module CalenderHelper
def calender(date = Date.today, &block)
Calender.new(self, date, block).table
end
**class Calender < Struck.new(:view, :date, :callback)**
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calender" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
week.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "notmonth" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
def weeks
first = date.beginning_of_month.beginning_of_week(START_DAY)
last = date.end_of_month.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
end
line with the error is marker with starts on each side
You have a small spelling mistake:
You want to call the Struct class, not Struck.
your line should be:
class Calendar < Struct.new(:view, :date, :callback)
# the rest of the code
end
Hope that helps

Translate the HEADER of RailsCast calendar

HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].map{ |key| I18n.t(key, scope: "table") }
but the I18n.locale is null so it gives me the default translation.
Even if I set I18n.locale = "ru" in the module CalendarHelper like that:
module CalendarHelper
def calendar(date = Date.today, &block)
Calendar.new(self, date, block).table
end
I18n.locale = "ru"
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].map{ |key| I18n.t(key, scope: "table") }
START_DAY = :sunday
.......
the I18n.locale is null and I get the default translation.
But if I set I18n.locale = "ru" within the class it works fine.
class Calendar < Struct.new(:view, :date, :callback)
I18n.locale = "ru"
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday].map{ |key| I18n.t(key, scope: "table") }
START_DAY = :sunday
.......
.........
how can I pass the params[:local] from the view to class Calendar or is there another solution to translate the HEADER?
Here's how I translated the headers. First, comment out the HEADER declaration...
class Calendar < Struct.new(:view, :date, :callback)
#comment out or remove the line below
#HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
START_DAY = :sunday
Then where the header is defined, replace the HEADER.map with I18n.t(:"date.day_names").map This pulls the day names directly from the config/locales/ *.yml files.
def header
content_tag :tr do
I18n.t(:"date.day_names").map { |day| content_tag :th, day }.join.html_safe
end
end
Now just declare the locale from the params in your controller and you should be all set.

loop not work in haml, but work in html.erb

It's very annoying,
Show nothing
- calendar #date do |date|
= date.day
But output of haml is in my expectation
<%= calendar #date do |date| %>
<%= date.day %>
<% end %>
This is my helper source code.
module CalendarHelper
require 'pry'
def widget
concat link_to("Hello", '')
concat " "
concat link_to("Bye", '')
end
def calendar(date = Date.today, &block)
cal_tbl = Calendar.new(self, date, block).table
# content_tag :div do
# cal_tbl
# end
# return cal_tbl
end
class Calendar < Struct.new(:view, :date, :callback)
HEADER = %w[Sunday Monday Tuesday Wednesday Thursday Friday Saturday]
START_DAY = :sunday
delegate :content_tag, to: :view
def table
content_tag :table, class: "calendar" do
header + week_rows
end
end
def header
content_tag :tr do
HEADER.map { |day| content_tag :th, day }.join.html_safe
end
end
def week_rows
weeks.map do |week|
content_tag :tr do
week.map { |day| day_cell(day) }.join.html_safe
end
end.join.html_safe
end
def day_cell(day)
content_tag :td, view.capture(day, &callback), class: day_classes(day)
end
def day_classes(day)
classes = []
classes << "today" if day == Date.today
classes << "notmonth" if day.month != date.month
classes.empty? ? nil : classes.join(" ")
end
def weeks
first = date.beginning_of_month.beginning_of_week(START_DAY)
last = date.end_of_month.end_of_week(START_DAY)
(first..last).to_a.in_groups_of(7)
end
end
end
As per the haml Git,
A hyphen(-), will run the code but not output the result
An equals sign(=), will output the result of the code
so it should be
= calendar #date do |date|
= date.day
Do this:
- calendar #date do |date|
= date.day
Well HAML to HTML translation follows this convention. the rails code that is supposed to be running and not shown is started with a - character, it is equivalent to <% rails code%> in HTML
= in HAML is equivalent of HTML <%= rails code %>, the closing <%end%> is auto generated in response to do rails code.
do this
= calendar #date do |date|
= date.day

Resources