I would like to keep a version of an object before it's updated.
For example:
This is the article on create:
#<Article:0x007fc32af4c910
id:1,
title: "Guitar",
price: 300,
buying_price: 50,
created_at: Sun, 17 Feb 2019 14:39:21 UTC +00:00,
updated_at: Sun, 17 Feb 2019 14:39:21 UTC +00:00,
>
This is an update of the article:
#<Article:0x007fc32af4c910
id:1,
title: "Guitar",
price: 300,
buying_price: 35,
created_at: Sun, 17 Feb 2019 14:39:21 UTC +00:00,
updated_at: Mon, 18 Feb 2019 14:39:21 UTC +00:00,
>
This the another update of the article:
#<Article:0x007fc32af4c910
id:1,
title: "Guitar",
price: 380,
buying_price: 45
created_at: Sun,17 Feb 2019 14:39:21 UTC +00:00,
updated_at: Wed, 20 Feb 2019 14:39:21 UTC +00:00,
>
See the the prices have changed, but I want to be able to report them all in an accounting table:
date | buying_price | price
17 feb |50 |300|
18 feb |35 |300|
20 feb |45 |380|
sorry I don't know how to create a table on markdown here
Accounting table is a DB table
You can use previous_changes do detect what changed and in a callback to update the accounting table.
class Article < ActiveRecord::Base
after_save :log_to_accounting_table
private
def log_to_accounting_table
p previous_changes
Accounting.create(....)
end
end
Not related to your issue: I'm using audited to track changes.
Accounting table is an Excel (what OP really wanted)
You'll need a table to store all those changes, "old versions" as you call them.
audited will help you. Then all you need to do is to export data from the audits table to a csv. Check this out to learn how to export to excel.
Related
I have a model where I am trying to come up with a query where I wanna select data if the starts_at is greater than today and the ends_at is less than today. The other caveat is checking if either one of those dates a NULL and if they aren't then the dates need to be checked against todays date also.
my_model.where("? >= starts_at AND ? <= ends_at OR (starts_at IS NULL OR ends_at IS NULL)", Ti
me.now.beginning_of_day, Time.now.end_of_day)
That code seems to pull back data sometimes and other times it doesn't.
** UPDATE **
Here are a few code examples
=> Menu Load (0.9ms) SELECT "menus".* FROM "menus" WHERE "menus"."account_id" = $1 AND ('2021-09-24 00:00:00' >= starts_at AND '2021-09-24 23:59:59.999999' <= ends_at OR (starts_at IS NULL OR ends_at IS NULL)) [["account_id", 1]]
[#<Menu:0x00005635d5657028
id: 4,
menu_type: "standard",
name: "Promo Menu",
starts_at: Fri, 24 Sep 2021 00:00:00.000000000 UTC +00:00,
ends_at: Fri, 01 Oct 2021 15:19:32.075844000 UTC +00:00,
never_ends: false,
account_id: 1,
created_at: Fri, 24 Sep 2021 00:37:44.127698000 UTC +00:00,
updated_at: Fri, 24 Sep 2021 16:03:06.558332000 UTC +00:00,
available: true>]
The above loads menus correctly, but heres a menu with a starts_at and ends_at within the query time frame and doesn't return
=> #<Menu:0x00005635d56d6e40
id: 1,
menu_type: "standard",
name: "Main Menu",
starts_at: Fri, 24 Sep 2021 00:37:43.512403000 UTC +00:00,
ends_at: Sat, 25 Sep 2021 17:46:13.450433000 UTC +00:00,
never_ends: false,
account_id: 1,
created_at: Fri, 24 Sep 2021 00:37:43.532613000 UTC +00:00,
updated_at: Fri, 24 Sep 2021 17:46:13.455113000 UTC +00:00,
available: true>
I think your query is correct. I guess you couldn't get the records sometimes because of the time zone. What's the timezone of the Rails app?
I'm using postgres database and trying to query all records with "Value"=>"Black" in this JSONB field. That field contain an array of objects, e.g. {"id"=>"1", "key"=>"size", "value"=>"P"}
How do I query(case-insensitive) this records?
This is my code so far
def by_feature_value(value)
relation.where('features #> ?', [{ value: value }].to_json)
end
Records
#<ProductSku:0x000055de9cc01ba8
id: 33,
product_id: 3,
code: "1234",
ean: "12345",
created_at: Mon, 30 Apr 2018 11:47:00 UTC +00:00,
updated_at: Mon, 30 Apr 2018 11:47:00 UTC +00:00,
features: [{"id"=>"2", "key"=>"Color", "Value"=>"Black"}]>
#<ProductSku:0x000055de9cc01ba8
id: 33,
product_id: 3,
code: "1234",
ean: "12345",
created_at: Mon, 30 Apr 2018 11:47:00 UTC +00:00,
updated_at: Mon, 30 Apr 2018 11:47:00 UTC +00:00,
features: [{"id"=>"2", "key"=>"Color", "Value"=>"black"}]>,
The correct answer to this is
ProductSku.where('lower(features::text)::jsonb #> lower(?)::jsonb', [{ Value: value }].to_json)
Without type casting the first comment on your post does not work.
I am building a RestAPI using Rails 5. I have 3 tables currently
Members
ContactSource (name)
ContactSourceMemberMap (member_id, contact_source_id, value)
Where,
class ContactSourceMemberMap < ApplicationRecord
belongs_to :member
belongs_to :contact_source
end
Now I want to fetch name from ContactSource and value from ContactSourceMemberMap.
I tried:
ContactSource.eager_load(:contact_source_member_maps).select("contact_sources.name", "contact_source_member_maps.value")
on ContactSourceMemberMap model.
The SQL which is getting generating is fetching data by performing INNER JOIN. But on the rails end its coming like
[#<ContactSource:0x007fa14f261950
id: 1,
name: "ContactSource1",
created_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00,
updated_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00>,
#<ContactSource:0x007fa14f200290
id: 2,
name: "ContactSource2",
created_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00,
updated_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00>,
#<ContactSource:0x007fa14fa8fb18
id: 3,
name: "ContactSource3",
created_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00,
updated_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00>,
#<ContactSource:0x007fa14fa8f2d0
id: 4,
name: "ContactSource4",
created_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00,
updated_at: Thu, 08 Mar 2018 16:33:00 UTC +00:00>]}]
It is not displaying the value field. Any thoughts why is it behaving like that?
contact_sources = ContactSource.eager_load(:contact_source_member_maps).select("contact_sources.name", "contact_source_member_maps.value")
and then you can get the other object with
contact_sources.first.contact_source_member_maps
if I am wrong you can check the following guide
I have a table which will have possible duplicate records.
id: 24,
name: "vamsi",
mobile: "7639817688",
company: "digi",
requirement: "mobile app",
created_at: Wed, 12 Oct 2016 11:05:33 UTC +00:00,
updated_at: Wed, 12 Oct 2016 11:05:33 UTC +00:00,
email_sent: false>,
#<Contact:0x00000006d7a4f0
id: 25,
name: "vamsi",
mobile: "7639817688",
company: "digi",
requirement: "mobile app",
created_at: Wed, 12 Oct 2016 11:05:57 UTC +00:00,
updated_at: Wed, 12 Oct 2016 11:05:57 UTC +00:00,
email_sent: false>]
Now I would like to find the unique records on which email_sent is false. I have tried this
Contact.where(email_sent: false).distinct
Contact Load (0.4ms) SELECT DISTINCT "contacts".* FROM "contacts" WHERE "contacts"."email_sent" = $1 [["email_sent", false]]
=> [#<Contact:0x00000006a1a698
id: 25,
name: "vamsi",
mobile: "7639817688",
company: "digi",
requirement: "mobile app",
created_at: Wed, 12 Oct 2016 11:05:57 UTC +00:00,
updated_at: Wed, 12 Oct 2016 11:05:57 UTC +00:00,
email_sent: false>,
#<Contact:0x00000006a1a418
id: 24,
name: "vamsi",
mobile: "7639817688",
company: "digi",
requirement: "mobile app",
created_at: Wed, 12 Oct 2016 11:05:33 UTC +00:00,
updated_at: Wed, 12 Oct 2016 11:05:33 UTC +00:00,
email_sent: false>]
But I would not want 2 records, since both are same. I would like only one to be shown. Is there any way I can solve this.
First part, the model should have validations so that these kinds of data won't be stored
It can be done via this
validates_uniqueness_of :name, scope: [:mobile, :requirement, :company]
Second part, still if you want to query something like above scenario. You have to do this
Contact.select(:name, :company, :mobile, :requirement).where(email_sent: false).distinct would be the query
ps: Answer picked up from all the comments in the question
Try group by email_sent after using where:
Contact.where(email_sent: false).group(:email_sent)
I got this model:
[#<Account:0x007fcf32153098
id: 1,
profit: 100,
user_id: 1,
created_at: Sun, 15 Nov 2015 02:27:43 UTC +00:00,
updated_at: Sun, 15 Nov 2015 02:27:43 UTC +00:00>,
#<Account:0x007fcf32152df0
id: 2,
profit: 500,
user_id: 1,
created_at: Sun, 16 Nov 2015 15:05:07 UTC +00:00,
updated_at: Sun, 15 Nov 2015 15:05:07 UTC +00:00>,
]
And for now I got this to group them in date:
Account.all.group_by{|a| a.created_at.strftime("%Y-%m-%d")}
{"2015-11-15"=>
[#<Account:0x007fcf3247b1a8
id: 1,
profit: 100,
user_id: 1,
created_at: Sun, 15 Nov 2015 02:27:43 UTC +00:00,
updated_at: Sun, 15 Nov 2015 02:27:43 UTC +00:00>],
"2015-11-16"=>
[#<Account:0x007fcf3247afc8
id: 2,
profit: 500,
user_id: 1,
created_at: Sun, 16 Nov 2015 15:05:07 UTC +00:00,
updated_at: Sun, 15 Nov 2015 15:05:07 UTC +00:00>]}
My question is: How can I group them and at the same time sum the profit together if there are more than one record for that day? Seems like I can't use sum(:profit) with postgres?
I think you can just do this simply with:
Account.order("DATE(created_at)").group("DATE(created_at)").sum(:profit)