How do I add a date column and integer column together using ActiveRecord? - ruby

I have two columns in a database once called purchase_date and the other called lifetime. I am trying to filter the results so that only the assets that are not passed their lifetime are shown when given the current tax year.
I've tried
Asset.where("? < DATE_ADD(purchase_date,INTERVAL lifetime YEAR) AND purchase_date >= ?",Date.new(2012,1,1),Date.new(2012,1,1))
But, then I realized that this would be tied to MySQL if it did work, which is fine if this was just going to work with my full aplication. But, I want something that is database agnostic especially since this is being tested against Sqlite. Sqlite with this query gives me the following exception:
ActiveRecord::StatementInvalid: SQLite3::SQLException: near lifetime
How can I add an integer column to a date column in my sql statement in an database agnostic way?
Update
I have played around with Squeel, but I don't think its going to work. It may be possible to detect the adapter and base it off of that.

Why not add an :expires_at field? You can set a :before_save hook to make sure it's automatically kept in sync with your :lifetime field.
before_save :set_expiration_date
scope :not_expired, where("expires_at > ?", DateTime.now)
def set_expiration_date
return unless purchase_date.changed? || lifetime.changed?
self.expires_at = purchase_date + lifetime.years
end

Related

Parse.com : query with two datetime at different column

I want to build sync method, both from my local database to parse.com and from parse.com to my local database. For first case ( from local to parse.com, Alhamdulillah my script run well. But for second case, i need query between column last_update and last_sync (i do not use updatedAt caused by i can't control it, so i use last_update).
Please explain me how to get all data if last_update is greaterThan last_sync?
From https://www.parse.com/questions/querying-between-two-dates i got query between two dates, but it's from same column, the value of query is real value. But my case, the value of key = last_update is column name, last_sync.
Thank you...
You can't use a query constraint that compares two columns. You need to change your logic. Why do you store both a last_update and last_sync in a record?
Syncing is a complex subject and you can easily mess up the logic. I don't understand how you can store a last_sync date on every record, as this has to be different for every user. You need to store the last_sync value for each user, and use that to compare against the last_update column on all records.

SQL column type from Arel::Attributes::Attribute object

tl;dr Given an Arel::Attributes::Attribue object, say Model.arel_table[:created_at] how do get it's SQL type?
Context: I'm bypassing the ActiveRecord infrastructure in favour of Arel to write some SQL reports that need to be generated really efficiently. Using Arel's to_sql method I'm generating the final SQL and executing it directly via ActiveRecord::Base.connection.execute. However, I need to apply SQL transformations to certain columns (eg. change timezone of timestamps stored in GMT). Since the number of columns is large (and varying, based on user input), I don't want to hard code these transformations. I'd like to look at the SQL type of the columns being selected and apply the transformation accordingly.
If you have the ActiveRecord class set up then you have access to its columns and columns_hash methods. Those will give you column objects (instances of ActiveRecord::ConnectionAdapters::Column) and there you should find type and sql_type methods. For example:
> Model.columns_hash['created_at'].type
=> :datetime
> Model.columns_hash['created_at'].sql_type
=> "timestamp without time zone"
The sql_type will be database-specific (that's PostgreSQL above), the type will match the type in your migrations so you probably want to use that instead of sql_type.
That said, you could probably get away with use the usual ActiveRecord relation methods (which should deal with conversions and time zones for you) and then call to_sql at the end:
sql = Model.where('created_at > ?', some_time).select('pancakes').to_sql
and then feed that SQL into execute or select_rows. That will let you use most of the usual ActiveRecord stuff while avoiding the overhead of creating a bunch of ActiveRecord wrappers that you don't care about.
Something that might be helpful specifically in arel is type_cast_for_database. This can be used on an arel table:
Model.arel_table.type_cast_for_database(:id, 'test')
=> 0
Model.arel_table.type_cast_for_database(:id, '47test')
=> 47
While you don't get the type specifically you can see if values like strings are going to be converted to a number or something.
EDIT
It's important to note that this only works if the arel table has a type_caster able_to_type_cast?. If you get it from the model like above, it should have a type caster.

Find records that were created closest to the current date

I would like to get the records that have their created_at date closest to the current date. How can I do this with active records' where clause?
You could find the closest record in the past with something like:
Record.where("created_at <= ?", Date.today).order_by("created_at DESC").limit(1)
Similarly, you can have the closest record in the future
Record.where("created_at >= ?", Date.today).order_by("created_at ASC").limit(1)
And then compare wich one is the closest to current date...
There may be a solution to do it with a single request, but I could not find how (if you're using SQL server, there's a method DATEDIFF that could help).
Update: Thanks to Mischa
If you're sure that all created_atare in the past, you're looking to the last created record, that could be written
Record.order("created_at").last
Update
To get all the records created the same date then the last record:
last_record_date = Record.max(:created_at)
Record.where(:created_at => (last_record_date.at_beginning_of_day)..(last_record_date.end_of_day))

Comparing ruby DateTime with sqlite Date

I am attempting to pull tweets from twitter and store them in an sqlite db. In order to prevent duplication I wish to ignore tweets where the user AND the time created already exist in the DB. So my code is
if Tweet.exists?(['twitter_created_at = ? AND from_user_id_str = ?', (tweet_results.created_at), tweet_results.from_user_id_str])
Now, through taking out the user_id parts i can tell that the problem is with the comparison between
twitter_created_at
tweet_results.created_at
I have been in the debugger and seen that the dates do match but i cannot get the statement to come back true.
thanks in advance.

Oracle: error while trying to use formulas

I created an element with an input value of type "Day" , when i write a formula i get this error.
Any idea what's wrong?
APP-FF-33232:
EATC_EXTRA_DAYS_ENTRY_EFFECTIVE_DATE_ENTRY_VALUE has null or not found allowed, but no
default set specified.
Cause: If a Database Item has
null allowed, or not found allowed,
then the item must also specify a
default set to be used to provide
default values in the event of these
occurring. The item named has one of
these conditions allowed, but the
default set column in the
FF_DATABASE_ITEMS table is null.
Action: Please refer to your
local support representative.
-
I'm not an expert in Oracle Apps (to say the least) but the error message is fairly clear. You - or someone - have written a Fast Formula which references a database column EATC_EXTRA_DAYS_ENTRY_EFFECTIVE_DATE_ENTRY_VALUE. Apparently this column can be nullable, in which case your Formula needs to provide a default value. Something like:
default for EATC_EXTRA_DAYS_ENTRY_EFFECTIVE_DATE_ENTRY_VALUE is 01-JAN-2010
Or perhaps you can use SYSDATE or CURRENT_DATE rather than a fixed value.
Solution to error: You called database item in Fast formula,
you need to initialize the date to specific date
alias EATC_EXTRA_DAYS_ENTRY_EFFECTIVE_DATE_ENTRY_VALUE as day
default for day is 01-jan-2010

Resources