Rake task to update records - ruby-on-rails

I am doing a rake task that is scrapping a website in order to find concerts:
lib/tasks/my_task.rake
task :find_concerts => :environment do
doc = Nokogiri::HTML(open(url))
data = doc.search('#dateconcert table')
data = data.css('.jaunec' ).map { |tr| tr.css('td').map(&:text) } + doc.css('.jaunef' ).map { |tr| tr.css('td').map(&:text) }
data.each do |concert|
c = Concert.new
c.date = concert[0]
c.city = concert[1]
c.save
end
end
What I want
I want to get an alert when a new concert is added ( on the website I am scrapping), so the tasks will be run everyday.
My problem
I want my Concerts list to be updated if there is a new record...
With the task I wrote it finds again the records that are already stored and duplicated them...
I only want the new records that could be found...
In the end I would like to compare what is new between the two last tasks in order to send an alert if something new was found.
EDIT
This is what data returns
[
["03 Décembre 2017", "PONT L\u0092ABBE (29) | Centre Culturel Le Triskell "],
["26 Janvier 2018", "MONTPELLIER (34) | Le Jam "],
["17 Février 2018", "BLOIS (41) | All That Jazz / Les Lobis "],
["22 Mars 2018", "MOISSAC (82) | Hall de Paris "],
["24 Mars 2018", "LAX (Baraqueville) (12) | Festival Lax'N Blues LAX\u0092N "],
["08 Décembre 2017", "ECHANGE CULTUREL CAMEROUN (0) | au 18 décembre 2017 - Organisation tournée MFR "],
["27 Janvier 2018", "LE THOR (84) | Le Sonograf "],
["16 Mars 2018", "CHAUMONT (52) | Le Nouveau Relax "],
["23 Mars 2018", "AUCH (32) | Le Cri'Art "]
]

I found a solution that may need some refactoring, though.
So I created two tasks,
find_concerts that will be run manually for the first scrap
update_concerts that will be run every day
task
require "nokogiri"
require "open-uri"
require "date"
require "time"
namespace :scrap do
desc "This get MM concerts"
url = "http://mountain-men.fr/concerts/"
doc = Nokogiri::HTML(open(url))
data = doc.search('#dateconcert table')
data = data.css('.jaunec' ).map { |tr| tr.css('td').map(&:text) } + doc.css('.jaunef' ).map { |tr| tr.css('td').map(&:text) }
task :find_concerts => :environment do
data.each do |concert|
c = Concert.create
c.date = concert[0]
c.city = concert[1]
c.save
end
end
task :update_concerts => :environment do
existing_date = Concert.all.map { |c| [c.date, c.city] }
data.each do |concert|
c = Concert.create
c.date = concert[0]
c.city = concert[1]
c.save unless existing_date.include?([concert[0], concert[1]])
end
Concert.where(city: nil, date: nil).destroy_all
end
end

I am not sure if I understand you correctly, but what you need to do is to check if it exists and other wise create.
I would do some thing like this.
task :find_concerts => :environment do
doc = Nokogiri::HTML(open(url))
data = doc.search('#dateconcert table')
data = data.css('.jaunec' ).map { |tr| tr.css('td').map(&:text) } + doc.css('.jaunef' ).map { |tr| tr.css('td').map(&:text) }
data.each do |concert|
Concert.where(data: concert[0], city: concert[1]).first_or_create
end
end
Now you only create if it doesn't exist. Then when you create one you can set a hook.
class Concern
after_create :send_notification
def send_notification
# send email here
end
end

Related

Ruby Seed - How to store subcategories for each sneaker and remove duplicates?

I want to create my database from CSV data. For that I have parse my file and I start to seed.
In my .csv file, there are sneakers name with subcategories like in the picture :
In my db/seeds.rb, i coded this :
# db/seeds.rb
csv_text = File.read(Rails.root.join('lib', 'seeds', 'air_jordan.csv'))
csv = CSV.parse(csv_text, :headers => true, :encoding => 'ISO-8859-1')
air_jordan_subcategories = ['1', '11', "Jordan OFF-WHITE", "Future", "Women", "High"]
csv.each do |row|
s = Sneaker.new
s.name = row['Name']
air_jordan_subcategories.each do |sub|
if row['Subcategory'] == sub
s.subcategory << sub
end
end
s.save
end
What I want is that the pair “Jordan 1 Mid Banned (2020)“, appears like this in my database:
=> #<Sneaker:0x00007ffdbd4a5980
id: 1,
name: "Jordan 1 Mid Banned (2020)",
subcategory : ["Mid", "1"]>
While for the moment, in my database I have 2 times the same pair because I have 2 different subcategories :
=> #<Sneaker:0x00007ffdbd4a5980
id : 1,
name : "Jordan 1 Mid Banned (2020)",
subcategory : ["Mid"]>
=> #<Sneaker:0x00007ffdbd4a5933
id: 2,
name : "Jordan 1 Mid Banned (2020)",
subcategory : ["1"] >
I can’t find a logical solution for this, what I would like is simply :
air_jordan_subcategories.each do |sub|
while row['category'] == sub
s.subcategory << sub
row += 1
end
end
But row += 1 doesn’t work, and while row['category'] == sub trigger an infinite loop.
Thanks for helping !

Can't loop through JSON data because of the error "no implicit conversion of hash into integer"

Hello and good afternoon all!
I am getting an error in my console that states "TypeError: No implicit conversion of hash into integer" and I know that it is referring to my loop in my Ruby class document.
Here is my Ruby file:
require 'HTTParty'
require 'pp'
require 'pry'
=begin
find a way to access the latitude and longitude of the nearest charging station globally
find a way to access the latitude and longitude of the user
create a function that finds the nearest station based on accepting both sets of coordinates and finds the difference
=end
class ChargingStations
include HTTParty
attr_accessor :pois
puts "loading"
##latitude = ''
base_uri 'https://api.openchargemap.io/v2'
def self.puts_latitude
puts ##latitude
end
def initialize(pois)
##pois = pois
##latitude = ##pois
puts ##pois
end
def self.put_value
puts ##latitude
end
def self.find_sites
for i in ##pois do
puts ##pois[i]
if ##pois[i]["AddressInfo"]["StateOrProvince"] == "New York"
puts ##pois[i]
end
end
end
def self.generate
response = get('/poi')
puts "got here"
if response.success?
puts "success"
self.new(response)
else
puts "failure"
raise response.response
end
end
end
binding.pry
If you are able to answer the question, please explain why my loop does not work for myself and future developers.
Thank you!
Why don't you give this a try:
class ChargingStations
include HTTParty
##latitude = ''
base_uri 'https://api.openchargemap.io/v2'
class << self
def pois
##pois
end
def puts_latitude
puts ##latitude
end
def put_value
puts ##latitude
end
def state_or_provinces
#state_or_provinces ||= ##pois.map do |poi|
poi.try(:[],'AddressInfo').try(:[],'StateOrProvince')
end.uniq
end
def find_sites(state_or_province=nil)
#state_or_province = state_or_province
#state_or_province ||= 'New York'
##pois.select do |poi|
poi.try(:[],'AddressInfo').try(:[],'StateOrProvince') == #state_or_province
end
end
def generate
response = get('/poi')
if response.success?
##pois = response.parsed_response
##latitude = ##pois
return true
else
puts "failure"
raise response.response
end
end
end # Class methods
end
Then, in console, I get:
ChargingStations.generate
=> true
ChargingStations.find_sites.count
=> 2
ChargingStations.find_sites.first
=> {"ID"=>112491, "UUID"=>"5EA5B030-AFEF-4CFA-88DF-3A9F6CFFDAB5", "ParentChargePointID"=>nil, "DataProviderID"=>1, "DataProvider"=>{"WebsiteURL"=>"http://openchargemap.org", "Comments"=>nil, "DataProviderStatusType"=>{"IsProviderEnabled"=>true, "ID"=>1, "Title"=>"Manual Data Entry"}, "IsRestrictedEdit"=>false, "IsOpenDataLicensed"=>true, "IsApprovedImport"=>true, "License"=>"Licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)", "DateLastImported"=>nil, "ID"=>1, "Title"=>"Open Charge Map Contributors"}, "DataProvidersReference"=>nil, "OperatorID"=>5, "OperatorInfo"=>{"WebsiteURL"=>"http://www.chargepoint.net/", "Comments"=>nil, "PhonePrimaryContact"=>"1-888-758-4389", "PhoneSecondaryContact"=>nil, "IsPrivateIndividual"=>false, "AddressInfo"=>nil, "BookingURL"=>nil, "ContactEmail"=>"support#coulombtech.com", "FaultReportEmail"=>"support#coulombtech.com", "IsRestrictedEdit"=>nil, "ID"=>5, "Title"=>"ChargePoint (Coulomb Technologies)"}, "OperatorsReference"=>nil, "UsageTypeID"=>1, "UsageType"=>{"IsPayAtLocation"=>nil, "IsMembershipRequired"=>nil, "IsAccessKeyRequired"=>nil, "ID"=>1, "Title"=>"Public"}, "UsageCost"=>"free", "AddressInfo"=>{"ID"=>112837, "Title"=>"1 Locks Plaza", "AddressLine1"=>"1 Locks Plaza", "AddressLine2"=>nil, "Town"=>"Lockport", "StateOrProvince"=>"New York", "Postcode"=>"14094", "CountryID"=>2, "Country"=>{"ISOCode"=>"US", "ContinentCode"=>"NA", "ID"=>2, "Title"=>"United States"}, "Latitude"=>43.169316400362, "Longitude"=>-78.6954369797903, "ContactTelephone1"=>nil, "ContactTelephone2"=>nil, "ContactEmail"=>nil, "AccessComments"=>"Located at the Lockport Municipal building, \"The Big Bridge\" and the \"Flight of Five\" locks 34 and 35 on the Erie Canal.", "RelatedURL"=>nil, "Distance"=>nil, "DistanceUnit"=>0}, "NumberOfPoints"=>1, "GeneralComments"=>"Located at the \"Big Bridge\" and \"Flight of Five\" locks 34 and 35 and the Lockport Municipal building", "DatePlanned"=>nil, "DateLastConfirmed"=>nil, "StatusTypeID"=>50, "StatusType"=>{"IsOperational"=>true, "IsUserSelectable"=>true, "ID"=>50, "Title"=>"Operational"}, "DateLastStatusUpdate"=>"2018-11-04T12:56:00Z", "DataQualityLevel"=>1, "DateCreated"=>"2018-11-04T05:18:00Z", "SubmissionStatusTypeID"=>200, "SubmissionStatus"=>{"IsLive"=>true, "ID"=>200, "Title"=>"Submission Published"}, "UserComments"=>[{"ID"=>20389, "ChargePointID"=>112491, "CommentTypeID"=>10, "CommentType"=>{"ID"=>10, "Title"=>"General Comment"}, "UserName"=>"Robert Seemueller", "Comment"=>"Located next to the Erie Canal's \"Flight of Five\" locks, downtown shops and restaurants.", "Rating"=>5, "RelatedURL"=>nil, "DateCreated"=>"2018-11-04T05:22:02.4Z", "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "CheckinStatusTypeID"=>10, "CheckinStatusType"=>{"IsPositive"=>true, "IsAutomatedCheckin"=>false, "ID"=>10, "Title"=>"Charged Successfully"}}], "PercentageSimilarity"=>nil, "Connections"=>[{"ID"=>158246, "ConnectionTypeID"=>1, "ConnectionType"=>{"FormalName"=>"SAE J1772-2009", "IsDiscontinued"=>nil, "IsObsolete"=>nil, "ID"=>1, "Title"=>"J1772"}, "Reference"=>nil, "StatusTypeID"=>50, "StatusType"=>{"IsOperational"=>true, "IsUserSelectable"=>true, "ID"=>50, "Title"=>"Operational"}, "LevelID"=>2, "Level"=>{"Comments"=>"Over 2 kW, usually non-domestic socket type", "IsFastChargeCapable"=>false, "ID"=>2, "Title"=>"Level 2 : Medium (Over 2kW)"}, "Amps"=>nil, "Voltage"=>nil, "PowerKW"=>nil, "CurrentTypeID"=>nil, "CurrentType"=>nil, "Quantity"=>2, "Comments"=>nil}], "MediaItems"=>[{"ID"=>16951, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405191125.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405191125.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:19:00Z"}, {"ID"=>16952, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405224211.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405224211.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:23:00Z"}, {"ID"=>16953, "ChargePointID"=>112491, "ItemURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.orig.2018110405240797.jpg", "ItemThumbnailURL"=>"https://s3-ap-southeast-2.amazonaws.com/openchargemap/images/US/OCM112491/OCM-112491.thmb.2018110405240797.jpg", "Comment"=>"", "IsEnabled"=>true, "IsVideo"=>false, "IsFeaturedItem"=>false, "IsExternalResource"=>false, "MetadataValue"=>nil, "User"=>{"ID"=>19108, "IdentityProvider"=>nil, "Identifier"=>nil, "CurrentSessionToken"=>nil, "Username"=>"Robert Seemueller", "Profile"=>nil, "Location"=>nil, "WebsiteURL"=>nil, "ReputationPoints"=>289, "Permissions"=>nil, "PermissionsRequested"=>nil, "DateCreated"=>nil, "DateLastLogin"=>nil, "IsProfilePublic"=>nil, "IsEmergencyChargingProvider"=>nil, "IsPublicChargingProvider"=>nil, "Latitude"=>nil, "Longitude"=>nil, "EmailAddress"=>nil, "EmailHash"=>nil, "ProfileImageURL"=>"https://www.gravatar.com/avatar/d8475a6af1852aa7fb2e1263c4ae5fac?s=80&d=mm", "IsCurrentSessionTokenValid"=>nil, "APIKey"=>nil, "SyncedSettings"=>nil}, "DateCreated"=>"2018-11-04T05:24:00Z"}], "MetadataValues"=>nil, "IsRecentlyVerified"=>true, "DateLastVerified"=>"2018-11-04T05:22:02.4Z"}
ChargingStations.find_sites('WA').count
=> 1
In general, when you use the construct for foo in fooArray to iterate over a Array, the foo is not the index but the actual item located in that position. So if you wanted your algorithm to work with minimal modifications, the "right" way would look like:
##pois.each_index do |i|
puts ##pois[i]
// rest of the algorithm ommited
end
In your case, assuming that the structure of your JSON data is something like [{lat: 10, lng: 10},{lat:5, lng:8}, {lat: 9, lng: -3], you are basically trying to do ##pois[{lat: 10, lng: 5}]], which will give you the exact "no implicit conversion" error that you're getting. You could just use i directly like puts i or i["AddressInfo"]["StateOrProvince"] and get the right answer.
However, as it has been mentioned in the comments, a more idiomatic approach would be ##pois.each do |poi|. And an even more idiomatic approach would be to rename that ugly-looking "pois" everywhere and make it
##positions.each do |position|
puts position
if position["AddressInfo"]["StateOrProvince"] == "New York"
puts position
end
end
Explicit variable names is the Ruby thing to do :)
And assuming the first puts is just a general test to see it's working and you actually want to only print the ones that are in New York...
##positions.each do |position|
puts position if position["AddressInfo"]["StateOrProvince"] == "New York"
end
And if you want to make that a one liner:
##positions.each { |pos| puts pos if pos["AddressInfo"]["StateOrProvince"] == "New York" }
(yeah, I know I just talked about explicit variable names but there is no need to be too rigid about it)

Rails 5: group datetime in hash of year, month, day

I have this query:
dates = MyModel.pluck("distinct date(datetime_column)")
Hash[dates.group_by(&:year).map{|y, items| [y, items.group_by{|d| d.month}]}]
which find distinct dates and then gives me this array:
=> {2017=>{12=>[Tue, 12 Dec 2017], 1=>[Sun, 01 Jan 2017]},
2016=>{11=>[Sun, 20 Nov 2016], 12=>[Sat, 24 Dec 2016, Mon, 12 Dec 2016, Fri, 30 Dec 2016]}}
How do I add 3rd level to have hash where there are particular days under each month? Thank you for any help!
Update
If someone needs ordered result, try this for "dates" part:
dates = MyModel.order(:datetime_column).distinct.pluck(:datetime_column)
For better performance can try to use this:
dates = MyModel.order("date_trunc('day', datetime_column) DESC")
.distinct.pluck("date_trunc('day', datetime_column)")
Here is nice blog post on using datetrunc.
You can use each_with_object, but you need to initialize the object correctly. It's a Hash of Hashes of Hashes!
require 'date'
a = Date.today
b = Date.new(2017,1,3)
c = Date.new(2015,12,5)
d = Date.new(2015,11,7)
dates = [a,b,c,d]
hash = Hash.new { |h, y| h[y] = Hash.new { |h2, m| h2[m] = {} } }
dates_by_ymd = dates.each_with_object(hash) do |date, h|
h[date.year][date.month][date.day] = date
end
require 'pp'
pp dates_by_ymd
# {2017=>
# {1=>
# {7=>#<Date: 2017-01-07 ((2457761j,0s,0n),+0s,2299161j)>,
# 3=>#<Date: 2017-01-03 ((2457757j,0s,0n),+0s,2299161j)>}},
# 2015=>
# {12=>{5=>#<Date: 2015-12-05 ((2457362j,0s,0n),+0s,2299161j)>},
# 11=>{7=>#<Date: 2015-11-07 ((2457334j,0s,0n),+0s,2299161j)>}}}
In your case, you'd write :
dates = MyModel.pluck("distinct date(datetime_column)")
hash = Hash.new { |h, y| h[y] = Hash.new { |h2, m| h2[m] = {} } }
dates_by_ymd = dates.each_with_object(hash) do |date, h|
h[date.year][date.month][date.day] = date
end
Note that this code returns Date objects as leaves of the nested hash, as you mentioned in your question.
If you want a modified version of your code, you can use this Rails code :
dates.group_by(&:year).map do |y, items|
[y, items.group_by(&:month).map { |m, days| [m, days.index_by(&:day)] }.to_h]
end.to_h
Try
dates = MyModel.pluck("distinct date(datetime_column)")
dates.group_by(&:year).map do |y, items|
[y, items.group_by(&:month).map { |m, days| [m, days.map(&:day)] }.to_h]
end.to_h

Rake task to update specific products in db

Hi all I've got a database full of products and I need to schedule a rake task to run every week.
I'm not exactly sure how to code the rake task. An example would be I have a product with id=1 name="testname" description="description" sku="198" price=12.99
I need to upload a csv with name="testname" and update the price to 13.99 while obviously keeping the id intact.
This is what I've tried so far but its not complete if anyone could help that would be great.
require 'csv'
desc "Updates Products inside an ActiveRecord table"
task :update_prods, [:filename] => :environment do
products = Spree::Product.all
CSV.foreach('update_prods.csv', :headers => true) do |row|
Spree::Product.update!(row.to_hash)
end
end
Here is a gist of how we imported products from Shopify to Spree which could give you some ideas on how to go about this https://gist.github.com/dgross881/b4f1ac96bafa2e29be7f.
def update_products
puts 'Updating Products...'
require 'csv'
products_csv = File.read(Rails.root.join('lib/assets/products_list.csv'))
products = CSV.parse(products_csv, headers: true)
products.each_with_index do |row, index|
Rails.logger.info { [#{index + 1}..#{products.length}] Updating product: #{row['title']} }
product = Spree::Product.find!(row['id'])
update_product = product.update_attributes(name: row['title'], description:row['description'],
meta_title: row['seo_title'], meta_description: row['seo_description'],
meta_keywords: "#{row['handle']}, #{row['title']}, the Squirrelz",
available_on: Time.zone.now, price: row['price'],
shipping_category: Spree::ShippingCategory.find_by!(name: 'Shipping'))
update_product.tag_list = row['tags']
update_product.slug = row['handle']
update_product.save!
end
Rails.logger.info { "Finished Updating Products" }
end
def update_variants
puts 'updating Variants...'
require 'csv'
products_variants_csv =File.read(Rails.root.join('lib/assets/variants_list.csv'))
products_variants = CSV.parse(products_variants_csv, headers: true)
products_variants.each_with_index do |row, index|
puts "[#{index + 1}..#{products_variants.length}] Adding Variant (#{row['sku']} to Product: #{Spree::Product.find_by!(slug: row['handle']).name})"
variant = Spree::Variant.find_by!(sku: row['sku']
update_variant = variant.update_attributes!(sku: row['sku'], stock_items_count: row['qty'], cost_price: row['price'], weight: row['weight']
unless row['option1'].blank?
variant.option_values << Spree::OptionValue.find_by!(name: row['option1'])
end
unless row['option2'].blank?
variant.option_values << Spree::OptionValue.find_by!(name: row['option2'])
end
variant.save!
end
puts 'Updated Variants'
end

Ruby on rails rake task not returning up-to-date model info

While building a billing system I encountered the following problem:
In scheduler.rake :
#users.each do |user|
begin
puts "CALCULATING COSTS =========="
costs = user.total_billable_price_per_month(Time.now)
lead_count = user.total_billable_leads_count(Time.now)
click_count = user.total_billable_clicks_count(Time.now)
puts "CREATING NEW INVOICES ======="
#invoice = user.invoices.new
# if user.free_credits
# invoice.total_price_in_cents = 0
# else
# invoice.total_price_in_cents = costs.cents
# end
#invoice.total_leads = lead_count
#invoice.total_clicks = click_count
#invoice.total_price_in_cents = costs.cents
# Als de vorige factuur onder de 10 euro was, dan geld bij huidige factuur optellen
if user.invoices.last && user.invoices.last.total_price_in_cents < 1000
puts "Bedrag onder 10 euro"
puts "Last invoice = #{user.invoices.last.total_price_in_cents}"
#invoice.total_price_in_cents += user.invoices.last.total_price_in_cents
end
puts "SAVING INVOICE FOR #{user.name} with ID = #{user.id}"
# Factuur saven
#invoice.save
#Als de factuur hoger of gelijk is als 10euro, dan factuur aanmaken
if #invoice.total_price_in_cents >= 1000
#Moneybird factuur versturen
puts "COSTS ARE HIGHER THAN 10 EURO, CREATING MONEYBIRD INVOICE"
moneybird_invoice = MoneybirdInvoice.new
sleep(15)
moneybird_invoice.contact_id = MoneybirdContact.find_by_customer_id(user.id).id
sleep(15)
moneybird_invoice.details_attributes = [
{ :description => "Aantal leads", :amount => lead_count, :price => user.lead_price.cents.to_f/100},
{ :description => "Aantal clicks", :amount => click_count, :price => user.click_price.cents.to_f/100}
]
puts "TRYING TO SAVE MONEYBIRD INVOICE"
if moneybird_invoice.save && moneybird_invoice.put(:send_invoice)
puts "SUCCESFULLY SAVED INVOICE"
#GET UPDATED PAY URL
#sent_mb_invoice = MoneybirdInvoice.get(moneybird_invoice.id)
sleep(15)
#invoice.update_attributes(:moneybird_invoice_id => #sent_mb_invoice['invoice_id'], :moneybird_pay_url => #sent_mb_invoice['pay_url'])
else
puts "MONEYBIRD INVOICE FAILED"
puts moneybird_invoice.errors.inspect
end
else
# GEEN MONEYBIRD FACTUUR AANMAKEN
end
rescue
puts "ER IS IETS FOUT GEGAAN MET FACTUREREN USER ID = #{user.id} & NAME = #{user.name}"
puts #invoice.errors.inspect
end
end
This piece of code should constantly increment each time the rake task is run, except when the total amount reaches > 1000.
if user.invoices.last && user.invoices.last.total_price_in_cents < 1000
puts "Bedrag onder 10 euro"
puts "Last invoice = #{user.invoices.last.total_price_in_cents}"
#invoice.total_price_in_cents += user.invoices.last.total_price_in_cents
end
The code above always puts "Last invoice = 100" => This should increment each time the rake tasks is run
Every new invoice still has the same total_price_in_cents (when I'm expecting that it should increment).
What is going on ?
EDIT: Added after code upadte:
In your updated code, it looks like you were calling user.invoices.last after you called user.invoices.new, this is why it always returned the same value.
Create a variable #last_invoice = user.invoices.last before call user.invoices.new.
ORIGINAL ANSWER:
In your original code posting, it looks like your save call on #invoice happened outside the loop -- I believe you're only saving it once.
task :create_invoices => :environment do
# Begin the loop for each use
User.all.each do |user|
#invoice = user.invoices.build
#If last bill < 1000
if user.invoices.last && user.invoices.last.total_price_in_cents < 1000
puts "Last invoice = #{user.invoices.last.total_price_in_cents}"
#invoice.total_price_in_cents += user.invoices.last.total_price_in_cents
#invoice.save
end # end 'if' statement
end # end loop for all users
end # end task definition
So you loop though the users table, but never save updates -- except for the very last time after you exit the loop

Resources