ruby check if current date is within date records - ruby-on-rails

Let's say I have a model called Absence that looks something like this
:id => :integer,
:employee_id => :integer,
:start_date => :date,
:end_date => :date
I need to check if an Employee is away today, and return true if they are. Someone is away if they have an absence record that
Has a start date is today or before today,
Has an end date that is either null, or today or ahead of today.
so I need a method on the Employee that is something like
def is_away
?????
end
please help!

I would do something like this:
# add this to absence.rb
def covers_today?
(start_date..end_date).cover?(Date.today)
end
# add this to employee.rb
def away?
absences.any?(&:covers_today?)
end
After doing this just call away? on an employee:
#employee.away?
# => true, if employee has an absense that covers the current date

Assuming that Employee has_many :absences, this should work:
def away?(date = Date.today)
absences.where('start_date <= :date AND (end_date >= :date OR end_date IS NULL)', date: date).exists?
end

You can try this too.
def is_away?
(start_date <= Date.today) and (end_date.nil? or end_date <= Date.today) ? true : false
end

Related

How to check if value unique for a certain period

I have a Ratings model with a phone_id attribute. Before creating a new ratings object I want to check if the phone_id is unique for the past week.
In my model I want to do something like this in the before_save callback:
self.all(:conditions => {:created_at => (1.week.ago..Date.today)}).include? self.phone_id
I would do it in clean sql (performance)
select count(phone_id) from ratings where created_at < DATE_SUB(NOW(), INTERVAL 1 MONTH)
You can use ActiveRecord validations with a constraint.
class Rating < ActiveRecord::Base
validates_uniqueness_of :phone_id, conditions: -> { where(:created_at => (1.week.ago..Date.today)) }
end
You can use validation on create:
class Rating < ActiveRecord::Base
validate :unique_phone_within_last_week?, on: :create
private
def unique_phone_within_last_week?
self.class.where("created_at > ?", 1.week.ago.to_date)
.where(phone_id: phone_id).empty? ||
errors.add(:phone_id, 'is not unique within last week') && false
end
end
In Rails 4 you can use validates_uniqueness_of with conditions proc:
class Rating < ActiveRecord::Base
validates_uniqueness_of :phone_id,
conditions: -> { where('created_at > ?', 1.week.ago.to_date) }
end
Read more about validates_uniqueness_of.
Checking SQL will be optimal:
SELECT COUNT(*) FROM "ratings"
WHERE "ratings"."phone_id" = 2 AND ("created_at" > '2014-01-14');
Note also that
Using interval 1.week.ago..Date.today is seems to be bad idea,
because records that were created today (in day of checking) are out of scope.
'2014-01-21 09:10:21' BETWEEN '2014-01-14 11:23:30' AND '2014-01-21' is false

Ruby on Rails Ransack Datetime to date search

Like carvil I have in my model a datetime for created_at although I wanted the "equals" predicate to compare the created_at and a date (like '2012-09-26').
So I added in my model (in order to add casted attributes and take off the old created_at/update_at/deleted_at :
ransacker :created_at do
Arel::Nodes::SqlLiteral.new("date(items.created_at)")
end
ransacker :updated_at do
Arel::Nodes::SqlLiteral.new("date(items.updated_at)")
end
ransacker :deleted_at do
Arel::Nodes::SqlLiteral.new("date(items.deleted_at)")
end
# Hide some attributes for advanced search
UNRANSACKABLE_ATTRIBUTES = ["created_at", "updated_at", "deleted_at"]
def self.ransackable_attributes auth_object = nil
(column_names - UNRANSACKABLE_ATTRIBUTES) + _ransackers.keys
end
But when I confirm the query (created_at equals to '2012-03-24') I have this error:
NoMethodError (undefined method `name' for "date(items.created_at)":Arel::Nodes::SqlLiteral):
Surprisingly, it works with "greater than" and "less than". Only "equals" occurs this error.
I made all of this for all my models and 60% works (the remain 40% occurs this error).
In the console :
irb(main):232:0> Item.search(:created_at_eq => Date.today.to_s).result
(Object doesn't support #inspect)
Thanks for your help
EDIT :
I have a default_scope which makes :
Item(:deleted_at false)
But I don't know why it occurs the error
Refer to second example of Ransack wiki,
in the model:
ransacker :created_at , type: :date do
Arel.sql('date(created_at)')
end
in the view:
<%= f.search_field(
:created_at_date_equals, placeholder: t(:date_format)
) %>
...
<%= sort_link(#search, :created_at, default_order: :desc) %>
config/initializers/ransack.rb
Ransack.configure do |config|
config.add_predicate 'date_equals',
arel_predicate: 'eq',
formatter: proc { |v| v.to_date }
validator: proc { |v| v.present? },
type: :string
end
The new predicate 'date_equals' is added for the date equal search. The ransacker declared with type: :date and get the date from datetime column with Arel
I had some problems with this, and came with this:
ransacker :created_at, type: :date do
Arel.sql('date(created_at)')
end
Please changes Arel::Nodes::SqlLiteral.new('date(column_name)') with Arel.sql('date(column_name)').
Your syntax will be ::
ransacker :created_at do
Arel.sql("date(items.created_at)")
end
ransacker :updated_at do
Arel.sql("date(items.updated_at)")
end
ransacker :deleted_at do
Arel.sql("date(items.deleted_at)")
end
I hove this would be helpful.

Show content based on holidays

ruby 1.9.2p290
rails 3.1.1
I have these models:
class Recipe < ActiveRecord::Base
belongs_to :festivity
end
class Festivity < ActiveRecord::Base
has_many :recipes
end
I have the following field in the "recipes" table:
festivity_id
And the following datetime fields in the "festivities" table:
starts_at
ends_at
How to display the content based on festivities dates?
I started think in this static way:
class PagesController < ApplicationController
def home
#recipes_by_festivities = Recipe.where(:festivity_id => 4).all(:order => 'RAND()', :limit => 8)
end
end
For example: In Xmas period (about all december month), I want to show a recipe list with the festivity_id = 1. In Thanksgiving period I wanna just a list of recipes with festivity_id = 4.
Am I clear? Let me know if I not.
SOLUTION
#current_festivity = Festivity.find(:last, :conditions => ["? between starts_at AND ends_at", Time.utc(0,Time.now.month,Time.now.day,0,0,0)])
#recipes_by_festivities = Recipe.where(:festivity_id => #current_festivity).all(:order => 'RAND()', :limit => 8)
What I would do is create a "name" field in the festivities table, then use the holidays gem to determine if there's a holiday on a specific date.
Holdays.on(Date.today)
Which will return a list of hashes: each hash has a name key. Then you could use that to look up the correct Festivity object current_festival = Festivies.where(:name => Holdays.on(Date.today)[0][:name]) and from there get the recipes: current_festival.recipes
This assumes starts_at and ends_at are saved with the same year (0), except if the period is in the middle of two years (Christmas time, for example): in that case, the ends_at year must be 1.
Festivity.create(name: 'Christmas time', starts_at: Time.utc(0,12,25,0,0,0), ends_at: Time.utc(1,1,6,23,59,59))
Festivity.create(name: 'Ferragosto', starts_at: Time.utc(0,8,15,0,0,0), ends_at: Time.utc(0,8,15,23,59,59))
Recipe.create(festivity: Festivity.find_by_name('Periodo natalizio'))
Recipe.create(festivity: Festivity.find_by_name('Ferragosto'))
# Searching for festivities today
Recipe.includes(:festivity).where(['? BETWEEN festivities.starts_at AND festivities.ends_at', Time.utc(0,Time.now.month,Time.now.day,12,0,0)]).all
# Searching for festivities on 15 August (in Italy there is a festivity that is called Ferragosto)
Recipe.includes(:festivity).where(['? BETWEEN festivities.starts_at AND festivities.ends_at', Time.utc(0,8,15,12,0,0)]).all
# Searching for festivities on 28 December
Recipe.includes(:festivity).where(['? BETWEEN festivities.starts_at AND festivities.ends_at', Time.utc(0,12,28,12,0,0)]).all
And this is a possible implementation of a function:
def recipes_on(day, month)
Recipe.includes(:festivity).where(['? BETWEEN festivities.starts_at AND festivities.ends_at', Time.utc(0,month,day,12,0,0)]).all
end
Since you want to find recipes by festivities, you can do this:
def home
festivity_today = some_custom_festivity_lookup(Time.now)
if !festivity_today.nil?
#recipes = Recipe.where(festivity_id: festivity_today.id).limit(8)
else
#recipes = Recipe.limit(8)
end
end

How to scope last week by Date object [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Scoping date attribute for this week?
I am trying to scope all of my Products for this week, so it should show all the products leading up to whichever day of the week.
class Product < ActiveRecord::Base
attr_accessible :purchase_date
def self.last_week # All prices of last week.
where(:purchase_date => 1.week.ago)
end
create_table :products do |t|
t.date :purchase_date
end
end
This code renders nothing in the view though so what do I need to correct?
ANSWER
For some reason I had to add advance(:days => -1) to in order to also retrieve Monday as well. You may not have to do this though.
def self.last_week
where(:purchase_date => 1.week.ago.beginning_of_week.advance(:days => -1)..1.week.ago.end_of_week).order("purchase_date desc")
end
UPDATED ANSWER
I had to do the advance(:days => -1) because of the Time zone I am in. I got rid of this by making sure I'm in my own Time zone. So now it can be normal as it should be:
def self.last_week
where(:purchase_date => 1.week.ago.beginning_of_week..1.week.ago.end_of_week)
end
And it should work correctly ONLY if you go by the default Rails Time zone or you config your own:
app/config/environment/development.rb
config.time_zone = "Eastern Time (US & Canada)"
Good luck.
This should do the trick:
scope :last_week, lambda { where("purchase_date >= :date", :date => 1.week.ago) }
scope :past_week, lambda { where("purchase_date >= :start_date AND purchase_date <= :end_date", {:start_date => 1.week.ago, :end_date => 1.day.ago }) }

Using Delta Indexes for associations in Thinking Sphinx

I have a Product model:
class Product < ActiveRecord::Base
belongs_to :subcategory
define_index do
# fields
indexes subcategory.name, :as => :subcategory, :sortable => true, :facet => true
# attributes
has subcategory_id, created_at, updated_at
#properties
set_property :delta => true
Now, suppose that a user updates a subcategory name, which is the proper way to update the products delta index?
According to this documentation: http://freelancing-god.github.com/ts/en/deltas.html, a save message should be sent to the product, so in this case I should go for each product related with the subcategory and send the save message, something like this:
class Subcategory < ActiveRecord::Base
has_many :products
after_save :set_product_delta_flag
private
def set_product_delta_flag
products.each { |product|
product.delta = true
product.save
}
end
end
I think that this is overkilling because we have like 100.000 products per subcategory.
Is this the correct way to update the delta index? Am I missing something?
After adding this:
def set_product_delta_flag
Product.update_all ['delta = ?', true], ['subcategory_id = ?', id]
Product.index_delta
end
I'm always receiving this error:
NoMethodError (undefined method `index_delta' for #):
So, the solution to this problem was to send the message *define_indexes* to the Product model.
After fixing this issue, everything was ok, but the delta_index was not correctly updated, I needed to do save twice to the subcategory model.
So my final solution is this one:
after_commit :set_product_delta_flag
private
def set_product_delta_flag
Product.define_indexes
Product.update_all ['delta = ?', true], ['subcategory_id = ?', id]
Product.index_delta
end
Using after_commit and define_indexes is the correct solution? Its the only one that I've found.
Try the following instead:
def set_product_delta_flag
Product.update_all ['delta = ?', true], ['subcategory_id = ?', id]
Product.index_delta
end
A single SQL statement, a single delta re-indexing. Should perform far better :)

Resources