Ruby use guard to assign variable inside if clause - ruby-on-rails

Is it possible to replace below if clause by guard?
end_date = if transaction_end_date.nil?
(starts_in_the_future ? start_date : today) + MIN_END_DATE
else
transaction_end_date
end

You can do this instead
end_date = transaction_end_date
end_date ||= (starts_in_the_future ? start_date : today) + MIN_END_DATE
or just
end_date = transaction_end_date ||
(starts_in_the_future ? start_date : today) + MIN_END_DATE

Related

How to get user's birthday based on day and month only

I want to have a member list for today's birthday and upcoming birthday(tommorow).
In users.controller.rb
def birthday
#birthday_users = User.all.order("created_at DESC").where(:birthday => Date.today)
end
def upcoming_birthday
#upcoming_birthday_user = User.all.order("created_at DESC").where(:birthday => 1.days.from_now )
end
These codes work only when the day, month and year are the same as today.
Example:
User 1's birthday = October 3 2018 (Showing on the birthday list)
User 2's birthday = October 3 2000 (Not showing on the birthday list)
In User model
PostgreSql
scope :today_birthday, { where('EXTRACT(month FROM birthday) = ? AND EXTRACT(day FROM birthday) = ?', Date.today.month, Date.today.day).order("created_at DESC") }
scope :upcoming_birthday, { where('EXTRACT(month FROM birthday) = ? AND EXTRACT(day FROM birthday) = ?', 1.days.from_now.month, 1.days.from_now.day).order("created_at DESC") }
MySql
scope :today_birthday, { where('MONTH(birthday) = ? AND DAY(birthday) = ?', Date.today.month, Date.today.day).order("created_at DESC") }
scope :upcoming_birthday, { where('MONTH(birthday) = ? AND DAY(birthday) = ?', 1.days.from_now.month, 1.days.from_now.day).order("created_at DESC") }
I'm assuming you want to find all users having a birthday today. So, you might want to ignore year and only consider month and day while querying. The below code might help you with that:
def birthday
#birthday_users = User.where('EXTRACT(month FROM birthday) = ? AND EXTRACT(day FROM birthday) = ?', Date.today.strftime("%m"), Date.today.strftime("%d"))
end
def upcoming_birthday
tomorrow = Date.today + 1.day
#upcoming_birthday_users = User.where('EXTRACT(month FROM birthday) = ? AND EXTRACT(day FROM birthday) = ?', tomorrow.strftime("%m"), tomorrow.strftime("%d"))
end

Greater/Lower than works but equals doesn't on >= and <= on .where()

I have a Rails 4 app and I'm trying to make a simple search for my invoices with 3 optional arguments: Name of the client, Start Date, End Date.
The search works fine mostly, if I put a start date and an end date it works for < and >, but eventhough i used >= and <=, if the invoice date is the same to either start or end, it just won't show on the result list.
The tables used look like this:
Client Table
ID
Name
The rest of the fields aren't necessary
Invoice Table
ID
Client_ID
Total_Price
Created_At *only here for relevance*
My Invoice Controller Search method looks like this:
def search
if request.post?
#count = 0
#invoices = Invoice.all
if params[:start_date].present?
#invoices = Invoice.invoices_by_date(#invoices, params[:start_date], 'start')
if #invoices.present?
#count = 1
else
#count = 2
end
end
if params[:end_date].present?
#invoices = Invoice.invoices_by_date(#invoices, params[:end_date], 'end')
if #invoices.present?
#count = 1
else
#count = 2
end
end
if params[:name].present?
#invoices = Invoice.invoices_by_client(#invoices, params[:name])
if #invoices.present?
#count = 1
else
#count = 2
end
end
if #count == 2
flash.now[:danger] = "No results found."
#invoices = nil
end
#name = params[:name]
#start_date = params[:start_date]
#end_date = params[:end_date]
end
end
And the Invoice Model methods i use look like this:
def self.invoices_by_client(invoices, name)
invoices= invoices.includes(:client)
.select('invoices.created_at', 'invoices.total_price', 'clients.name')
.where("clients.name LIKE ?", "%#{name}%")
.references(:client)
return invoices
end
def self.invoices_by_date(invoices, date, modifier)
if modifier == 'start'
invoices = invoices.includes(:client)
.select('invoices.created_at', 'invoices.total_price', 'clients.name')
.where("invoices.created_at >= ?", date)
.references(:client)
elsif modifier == 'end'
invoices = invoices.includes(:client)
.select('invoices.created_at', 'invoices.total_price', 'clients.name')
.where("invoices.created_at <= ? ", date)
.references(:client)
end
return invoices
end
It probably isn't the best solution overall and I don't know if i did anything wrong so it would be great if you guys could help me with this.
I followed Alejandro's advice and messed around with the time aswell as the date, something like this:
if modifier == 'start'
invoices = invoices.includes(:client)
.select('invoices.created_at', 'invoices.total_price', 'clients.name')
.where("invoices.created_at >= ?", "#{date} 00:00:00") // Added the start time
.references(:client)
elsif modifier == 'end'
invoices = invoices.includes(:client)
.select('invoices.created_at', 'invoices.total_price', 'clients.name')
.where("invoices.created_at <= ? ", "#{date} 23:59:59") // Added end time aswell
.references(:client)
end
I forced the time for the start date as 00:00:00 and the time for the end date as 23:59:59 and it worked as desired. Thank you for the help man and i hope this helps other people!

Rails: How to loop through month?

I made a scope help me to select objects
scope :best_of_the_month, ->(year, month) do
time = Time.new(year, month)
start_time = time.beginning_of_month
end_time = time.end_of_month
where("created_at > ? AND created_at < ?", start_time, end_time).where("likes > ?", 15).where("rating > ?", 4.85).order_by_rating.to_a.uniq(&:author)
end
Then, I want to loop through this method, from 2014/1 to now. How can I do it?
Maybe something like this:
start_date = Date.create(2014,1).month
end_date = Date.today.month
#monthly_videos = []
(start_date..end_date).each do |year, month|
videos = Video.best_of_the_month(year, month)
#monthly_videos << videos
end
I find a solution here, How to Loop through Months in Ruby on Rails. But it seems about looping through the days. Not the month
With the best_of_the_month scope defined to take month and year as params, the following code should work:
date = Date.new(2014,1,1)
#monthly_videos = []
while true
videos = Video.best_of_the_month(date.year, date.month)
#monthly_videos << videos
date += 1.month
break if date == Date.today.beginning_of_month
end
You could use the Date#next_month method
date = Date.new(2014,1,1)
final_date = Date.new(Date.today.year, Date.today.month)
#monthly_video = []
loop do
#monthly_videos << Video.best_of_the_month(date.year, date.month)
break if date == final_date
date = date.next_month
end

Grails - find where date ranges overlap

I have a Grails domain object with a startDate and endDate property.
What's the best way to find all those objects where the range [startDate, endDate] overlaps with a specified date range? I know how to do this in SQL but wonder if there's any Grails/GORM magic to do it more succinctly.
Also, the endDate is an optional property.
The SQL / JPQL query would be something like
from MyObject obj where obj.startDate <= ?1 and (obj.endDate is null OR obj.endDate >= ?2)
Two Ways to embrace Grails/GORM in this case:
Lazy:-
def today = new Date()
def query = MyObject.where {
startDate <= (today - 10) && (endDate == null || endDate >= today + 10)
}
def listOfMyObjects = query.list()
Eager:-
def today = new Date()
def listOfMyObjects = MyObject.findAll {//or find{} if you need the first occurance
startDate <= (today - 10) && (endDate == null || endDate >= today + 10)
}

plus 1 to integer record for each record in DB

I need plus some value to integer column for many records in db.
I'm trying to do it in "clean" way:
Transaction.where("account_id = ? AND date > ?", t.account_id, t.date).
update_all("account_state = account + ?", account_offset)
or
Transaction.where("account_id = ? AND date > ?", t.account_id, t.date).
update_all("account_state += ?", account_offset)
i get error:
QLite3::ConstraintException: constraint failed:
UPDATE "transactions" SET account_state = (account_state + ?)
WHERE (account_id = 1 AND date > '2012-03-01') AND (-10000)
But works "dirty" way:
Transaction.where("account_id = ? AND date > ?", t.account_id, t.date).
update_all("account_state = account + #{account_offset}")
Is there any "clean" way to do this?
The second parameter of update_all is not the value of the ?, but the conditions (optional) of the SQL request.
You may try with
Transaction.where("account_id = ? AND date > ?", t.account_id, t.date).update_all(["account_state = account + ?", account_offset])

Resources