Rails re-formatting my datetime - ruby-on-rails

I have a big query, which collects a collection of models, and I need to format the timestamps in the following manner: YYYY-MM-DDTHH:MI:SS.MSZ
So, my query looks like:
models.select("(to_char(created_at, 'YYYY-MM-DD') || 'T' || to_char(created_at, 'HH24:MI:SS.MSZ')) AS created_at").as_json
But, when I get the result, I still get created_at field as a DateTime object.
Nevertheless, if I rename the field in something else, like AS something_else, then I have my required format.
How can I fix the problem, so that it will return created_at in my format, without going through the whole collection, and formatting each model ?
UPDATE
Database I am using is PostreSQL
I traced this behaviour back to ActiveSupport::JSON::Encoder. I use the gem activesupport-json_encoder because I need the setting ActiveSupport.encode_big_decimal_as_string = false, while since Rails 4.1 they by default are encoded as strings.
Now, this Encoder is encoding created_at and updated_at fields as ActiveSupport::TimeWithZone.
Can I get rid of the latter somehow ?

Related

Rails + PostgreSQL: if value in one column is NULL, search by a value in a different column

In my model, I have these columns:
customer_invoiced_at: datetime
customer_invoice_at_custom: datetime
I am trying to search all records where the given date matches customer_invoiced_at:
scope :by_customer_invoiced_at_from, (lambda do |date_from|
self.where("customer_invoiced_at >= ?", date_from.to_datetime.beginning_of_day) if date_from.present?
end)
I'd need to tweak it a bit - if customer_invoice_at_custom exists (is not null or empty), I would need to use this field instead of customer_invoiced_at. However, if customer_invoice_at_custom is NULL or empty, I'd want to use customer_invoiced_at (as it is now in the shown scope).
How do I achieve that?
Thank you in advance
Can you use PostgreSQL's native COALESCE() function? This does exactly what you want:
.where("COALESCE(customer_invoiced_at, my_other_column) >= ?", date_from.to_datetime.beginning_of_day)

Getting Unix Time from Active Record ruby on rails

I have one table Bandwidth where I am saving user_traffic and created_at fields. I want to return user_name and created_at but I want date to be in Unix Time stamp in ruby on rails without using Query but by activerecord.
Bandwidth.all.select("user_traffic,created_at")
Above return both but in normal date format, but I want it to be in Unix
created_at: "2019-06-26 11:28:39", user_traffic: 0
I tried following and it works, but I could not get other column in this.
Bandwidth.find_by(id: 2).created_at.to_i
It return just timestamp which is perfect but how can I add other columns in this query. I think it is using model function to_i
=> 1561548975
If you don't need the relation later, you can use map to make any data format you want.
EX:
Bandwidth.all
.select(:user_traffic, :created_at)
.map{|b| [b.user_traffic, b.created_at.to_i]}

'Time' being changed to a 'Datetime' after being added to a hash

My controller creates something called start_time. When I print start_time's value before it's added to a LittleClassSession hash, here's what I get:
22:45:00
Okay, it looks like a value with the type time. After it's added to the hash, I ask the controller what the :start_time value is.
#little_class_session = LittleClassSession.new({
...
:start_time => start_time
})
puts #little_class_session.start_time
Here's what it puts:
2000-01-01 22:45:00 UTC
It appears to be formatted like a datetime, but asking what the .class of the start_time attribute is returns:
Time
The LittleClassSession start_time column is a time in the table (I can verify this by checking the type in the Rails console) but was a datetime when the model was created.
What could be causing this?
While your database may support a "time" column (meaning just a time with no date information), Rails by default does not (largely because neither does Ruby's standard library -- even a Time contains date information). As such, when you assign it to your model, Rails is coercing it into the type it knows how to deal with, DateTime. So, you have a few options:
Ignore the date part of the time when you use it.
Use a gem like tod to deal with your time-only types, and follow the guidelines in the README for hooking it up to Rails.
Store start_time_hour and start_time_minutes in two separate columns, and work with them as needed (e.g, Date.current + start_time_hour.hours + start_time_minutes.minutes).
Hope that helps!

Find a record by bigint column with wildcard

I have an API that has a database with UPC-12 values in it. Sometimes API calls will come in with UPC-10 codes. My db upc column is bigint, so it removes the leading 0 on a UPC-12 value. That leaves the last digit as a wildcard when comparing to UPC-10.
I'd like to be able to check a UPC-10 value against records in the db to see if there's a match. Since I can't use LIKE, how do I do that?
The goal is to do something like:
def self.pull_product(upc)
upc_string = upc.to_s
if upc_string.length == 10
# product = Product.where... use a wildcard to try and match to existing record
else
product = Product.find_by_upc(upc)
end
end
This Rails 4 and Postgresql.
Just to clarify:
I might have a UPC-10 api call with a upc param like: 7618600002. My database has the UPC-12 equivalent: 76186000023. So if I just query for the param in the api call, I'll get nil.
I need a way to match the the UPC-10 param against my UPC-12 value in the database.
You need to use SQL like this:
upc between upc_string::int*10 and upc_string::int*10+9
I have no idea how to code it in Rails though.

Best way to store ISO8601 in datetime column in Rails?

I'm passing my Rails controller a parameter that has a value of:
time = "2011-11-14T23:53:14.000Z"
For my app, I have a a database called "Reminders" with a remind_at column, which is a datetime column just like created_at and modified_at.
However I can't figure out how I should save this. I imagine it would be something like:
r = Reminder.create(:remind_at => time)
r.save
But this does not save it properly. Am I supposde to do some conversion of some sort first? Any thoughts?
Yes, you need to convert it into a Time object:
time = Time.parse("2011-11-14T23:53:14.000Z")

Resources