Count Records within 30 days of today - ruby-on-rails

I Have a model an Opportunity model that has an attribute called date_of_opportunity. I am trying to write a method that counts how many opportunities are within 30 days of today. However when I try to call my method in the console, I get the error 'undefined local variable or method'
Here is my model:
class Opportunity < ActiveRecord::Base
def calculate_num_days
num_days = 0
#opportunity = Opportunity.all
#opportunity.each do |opportunity|
if (opportunity.date_of_opportunity - Date.today < 30)
num_days = num_days + 1
return num_days
end
end
end
end
Can someone help me figure out whats wrong? Thanks!!

If you will get counts how many opportunities are within 30 days of today, you can try this :
class Opportunity < ActiveRecord::Base
def self.calculate_num_days(from = (Date.today-1.month).beginning_of_day,to = Date.today.end_of_day)
where(date_of_opportunity: from..to).count
end
end
And on your console you can type like this
Opportunity.calculate_num_days
Output looks like :
irb(main):001:0> Opportunity.calculate_num_days
←[0m←[1m←[35m (51.0ms)←[0m SELECT COUNT(*) FROM "opportunities" WHERE ("opportunities"."date_of_opportunity" BETWEEN '2014-05-04 00:00:00.000000' AND '2014-06-04 23:59:59.999999')
=> 2

You seem to want a class method, but are defining an instance method. Do this:
def self.calculate_num_days
...
end

Maybe, #opportunity = Opportunity.all should be #opportunities = Opportunity.all

Unless I am missing what you are trying to do I would let ActiveRecord do the heavy lifting. Opportunity.where("date_of_opportunity - :today < 30", today: Date.today).size
Disclaimer, this is completely untested

Related

Rails 4: Sorting by 2 different scopes/class methods

I'm trying to sort my events by future events then by events that have already ended. I tried using 2 different scopes but I'm thinking now that I might need to use class methods instead. I'm just struggling on how, syntactically, I need to write these methods.
event.rb:
def active
self.event_date > Time.now
end
def inactive
self.event_date < Time.now
end
"event_date" is a datetime column in the events table.
events_controller.rb:
def index
#events = Event.all.sort_by {|a,b| [a.active, b.inactive]}
end
With this code, I'm getting an error: "undefined method `inactive' for nil:NilClass" but I've tried it several different ways and can't seem to figure out how to write it.
Your methods will be executed after running through the database and will be slow.
This can probably be improved:
Model
scope :active, -> { where('event_date >= ?', Time.now) }
scope :inactive, -> { where('event_date < ?', Time.now) }
Controller
#active_events = Event.active
#inactive_events = Event.inactive
#events = #active_events + #inactive_events

Rails: error charting by time

I am creating a chart based on account balance. And here is my some of my codes
module AccountsHelper
def products_chart_data
orders_by_day = Account.total_grouped_by_day(3.days.ago)
(3.days.ago.to_date..Date.today).map do |date|
{
created_at: date,
balance: orders_by_day[date].first.try(:total_balance) || 0
}
end
end
end
class Account < ActiveRecord::Base
belongs_to :user
has_many :books
def self.total_grouped_by_day(start)
balances = where(created_at: start.beginning_of_day..Time.zone.now)
balances = balances.group("date(created_at)")
balances = balances.select("created_at, balance as total_balance")
balances.group_by {|o| o.created_at.to_date }
end
end
My problems are:
1) I received an error undefined method `first' when mapping 3.days.ago, but successfully run the code when I change it to 2.days.ago. I understand that it is because I do not have data on 3 days ago as this account is new. My question is, how can I rescue this error, because I could have many other new accounts that do not have data yet, and what could I do to display result for 1 month, or 2 month?
Thanks in advance!
# ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓
balance: orders_by_day[date].try(:first).try(:total_balance) || 0
try is the method, introduced by rails and defined on Object class, therefore it is defined on NilClass as well.
The implementation is quite straightforward: it checks whether receiver is empty and returns either the result of the call to it, or nil otherwise.

Method to return a collection - Ruby

Say, I have a method called posted_listings, which is supposed to run an ActiveRecord query and return a collection of User.listings where posted: true, with posted? being a Listing class method. So far I have been doing:
class Bar < ActiveRecord::Base
def posted_listings
posted_listings = []
listings.each { |listing| posted_listings << listing if listing.posted? }
posted_listing
end
end
but each time this query runs I start feeling really bad about my skills (or lack of thereof). What is the most efficient way to return a collection of posted listings?
Edit:
posted? is not an attribute, its a class method:
class Listing < ActiveRecord::Base
def posted?
true if quantity >= 1 && has_sellers?
end
end
def has_sellers?
sellers.count >=1 #association to Seller
end
I would recommend adding a scope to your Listing model like this:
scope :posted, -> { where(posted: true) }
Then you can get all posted listings like this:
#user.listings.posted
You can learn more about scopes here if you are interested.
UPDATE
Try this scope instead:
def self.posted
joins(:sellers)
.where('posted = ? AND quantity > ?', true, 0)
.group('listings.id')
.having('COUNT(sellers.id) > ?', 0)
end
Your question is not so clear for me.
You may try:
User.listings.where(posted: true)
to get all users' posted Listings.
Or, saying #useris an User instance:
#user.listings.where(posted: true)
to get posted Listings from an specific user.

Variables that store DB queries in Ruby on Rails

I have a little Rails beginners question:
inside my Rails helper, I created method that I'm using to show a price in my view:
def price
pricea = Hotel.order(wdpricenm: :asc).first
priceb = Hotel.order(wepricenm: :asc).first
if (pricea.wdpricenm + priceb.wepricenm) < (priceb.wdpricenm + priceb.wepricenm)
return (pricea.wdpricenm + priceb.wepricenm)
else
return (priceb.wdpricenm + priceb.wepricenm)
end
<td><%= price %></td>
Its works without problems but I'd like to put the pricea / priceb variables (that store the queries) somewhere else in the rails application since I want to use them for other methods as well.
My Question is therefore: What would you suggest where to put those price variables in Rails and especially what variable types would you use?
Thanks for all replies in advance,
Cheers Rob
Use scope: http://guides.rubyonrails.org/active_record_querying.html#scopes
Class Hotel < ActiveRecord:Base
scope :pricea, -> { order(wdpricenm: :asc).first }
scope :priceb, -> { order(wepricenm: :asc).first }
end
Class Hotel < ActiveRecord:Base
def self.pricea
self.order(wdpricenm: :asc).first
end
def self.priceb
self.order(wepricenm: :asc).first
end
end
Now you are able to use:
pricea = Hotel.pricea
priceb = Hotel.priceb
If you need those prices available in different views you can do in the controllers:
Before_action :retrieve_prices, only: [:action1, :action2]
def retrieve_prices
#pricea = Hotel.pricea
#priceb = Hotel.priceb
end
This way this variables will be available only for the selected actions, and the methods can be reused anywhere.
EDIT: per comment
In the model:
Class Hotel < ActiveRecord::Base
scope :weekday_min, -> { where(minimum(:wdpricenm)).first }
scope :weekend_min, -> { where(minimum(:wepricenm)).first }
def self.best_deal(weekdays, weekend_days)
weekday_min_tot = (weekdays * weekday_min.wdpricenm) + (weekend_days * weekday_min.wepricenm)
weekend_min_tot = (weekend_days * weekend_min.wdpricenm) + (weekend_days * weekend_min.wepricenm)
[weekday_min_tot, weekend_min_tot].min
end
end
In the controller:
#best_deal = Hotel.best_deal
Display total price in the view(no hint as to which hotel though):
<%= #best_deal %>
Note the lack of helpers.
ALSO NOTE: The best deal might not be either of these choices. What you need is to calculate the total for each hotel and then take the minimum of that.
You have a bit of a journey ahead of you picking up Rails. It's a big bite. I recommend the Hartl tutorial to start with. And don't forget to learn Ruby.

ActiveRecord where method datetime passed

Thanks for your continuing support in my latest venture in a Rails app. It's been a while since I've made something in Rails so here is my latest question. I appreciate the help you've all given in the past.
I have a Model called Event.rb which contains a date:date and time:time fields for the Event.
I also have a method inside of the model which is..
def begins
DateTime.new(date.year, date.month, date.day, time.hour, time.min, time.sec)
end
As I can't see if something has truly passed because I only have Date and Time separate so I need them together.
My question is...
I want to be able to add in the DateTime :begins into the following other method in my Model...
def self.past
where("date <= ?", TIME_NOW)
end
Just like I have a method which is...
def upcoming?
self.date >= Time.now
end
Which I could easily change self.date to begins and would past I would imagine?
Thanks!
Perhaps something like this will work for querying the database for past events using your existing date and time columns:
scope :past, lambda {
where("date <= ? and time <= ?",
Time.now.strftime("%Y-%d-%m"),
Time.now.strftime("%H:%M:%S")
)
}
past_events = Event.past
For checking the current instance, you could continue to use your begins method:
def past?
begins < DateTime.now
end
#event = Event.first
#event.past?

Resources