line 212 of postgresql_adapter.rb is return Time.now.to_s if value =~ /^\(''now''::text\)::(date|timestamp)/ i don''t think this will work. in postgresql the field ''now'' is pinned to the SAME TIME for the duration of a transaction. eg. if you do begin transaction; insert into t values(42, ''now''); # sleep one minute insert into t values(42, ''now''); # sleep one minute insert into t values(42, ''now''); commit; and fields will have the same timestamp. for example: [ahoward@localhost ~]$ cat a.rb require ''open3'' stdin, stdout, stderr = Open3::popen3 ''psql'' stdin.puts ''drop table t;'' stdin.puts ''begin transaction;'' stdin.puts ''create table t(ts timestamp);'' 4.times{ stdin.puts "insert into t values(''now'');"; sleep 1} stdin.puts ''end transaction;'' stdin.puts ''select * from t;'' stdin.close puts stdout.read [ahoward@localhost ~]$ ruby a.rb ... ... ... ts ---------------------------- 2005-03-03 09:53:54.290717 2005-03-03 09:53:54.290717 2005-03-03 09:53:54.290717 2005-03-03 09:53:54.290717 (4 rows) it looks like (from only reading the code) that table_structure will map the default values of each field in column_defaults.collect do |row| field = row[0] type = type_as_string(row[3], row[2]) default = default_value(row[1]) length = row[2] [field, type, default, length] end so, each time default_value sees ''now'' it will call Time::now.to_s - and this will be different each time. it may not be obvious right away since, if the code runs quickly and you are storing only to second resolution you might not notice, but this could lead to subtle errors. in any case, i may be way off base here : but what i''ve done in the past with my own postgresql orms is to have a class variable @@now, which gets reset each time a transaction is started using select current_timestamp; and is then used during transaction for any ''now'' -> ruby translations. of course, if you are not using transactions this must be reset for each statement. basically some sort of lazy evaluation which depends on the transaction context is needed to do the mapping of the ''now'' string to a time object... can anyone comment on this? kind regards. -a -- ==============================================================================| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | When you do something, you should burn yourself completely, like a good | bonfire, leaving no trace of yourself. --Shunryu Suzuki ===============================================================================
> line 212 of postgresql_adapter.rb is > > return Time.now.to_s if value =~ /^\(''now''::text\)::(date|timestamp)/ > > i don''t think this will work. in postgresql the field ''now'' is pinned > to the > SAME TIME for the duration of a transaction. eg. if you doWell, it does work, but as you mentioned, it does introduce the subtle difference you mentioned. <snip>> 2005-03-03 09:53:54.290717 > 2005-03-03 09:53:54.290717 > 2005-03-03 09:53:54.290717 > 2005-03-03 09:53:54.290717 > (4 rows)Checking over the docs again, you''re right, this is what the behavior is supposed to be. <snip>> so, each time default_value sees ''now'' it will call Time::now.to_s - > and this > will be different each time. it may not be obvious right away since, > if the > code runs quickly and you are storing only to second resolution you > might not > notice, but this could lead to subtle errors. > > in any case, i may be way off base here : but what i''ve done in the > past with > my own postgresql orms is to have a class variable @@now, which gets > reset > each time a transaction is started using > > select current_timestamp; > > and is then used during transaction for any ''now'' -> ruby > translations. of > course, if you are not using transactions this must be reset for each > statement. basically some sort of lazy evaluation which depends on the > transaction context is needed to do the mapping of the ''now'' string to > a time > object... > > can anyone comment on this?The problem I had when I wrote this patch originally was that CURRENT_DATE, CURRENT_TIMESTAMP, ''now'', and ''now()'' - all which would accomplish the desired effect in PostgreSQL wouldn''t get properly sent up the chain of the AR call stack. Maybe I just missed the following: Looking over the code again, I think if we switched to using ''now'' as the value and modified the string_to_time function in abstract_adapter.rb to be: def string_to_time(string) return string if string.is_a?(Time) return Time.now if string == ''now'' time_array = ParseDate.parsedate(string).compact # treat 0000-00-00 00:00:00 as nil Time.send(Base.default_timezone, *time_array) rescue nil end (The second line, return Time.now... is my addition here - sorry its not a proper diff.) Then we''d have the desired result. string_to_date would need a similar modification I believe. Ara, I do not have time to put together a patch and test it at the moment, could you? Regards, -- Dave Steinberg http://www.geekisp.com/ http://www.steinbergcomputing.com/
On Thu, 3 Mar 2005, Dave Steinberg wrote:> Well, it does work, but as you mentioned, it does introduce the subtle > difference you mentioned.and, of course, the subtlty depends on how long your transactin takes : the longer it takes the worse the error becomes... basically it''ll work in testing but not production - slippery.> The problem I had when I wrote this patch originally was that CURRENT_DATE, > CURRENT_TIMESTAMP, ''now'', and ''now()'' - all which would accomplish the > desired effect in PostgreSQL wouldn''t get properly sent up the chain of the > AR call stack. Maybe I just missed the following: > > Looking over the code again, I think if we switched to using ''now'' as the > value and modified the string_to_time function in abstract_adapter.rb to be: > > def string_to_time(string) > return string if string.is_a?(Time) > return Time.now if string == ''now'' > time_array = ParseDate.parsedate(string).compact > # treat 0000-00-00 00:00:00 as nil > Time.send(Base.default_timezone, *time_array) rescue nil > end > > (The second line, return Time.now... is my addition here - sorry its not a > proper diff.) > > Then we''d have the desired result. string_to_date would need a similar > modification I believe.i don''t think this will work - acknowledging here that i''ve only read about 10% of the rails source. here''s why; you can only skin this cat two ways: - sychronize the postgresql adapters notion of ''now'' with that of the database. this means knowing if you''re in a transaction or now, and even this is doomed to be a ''little'' wrong since there is always some time that has elapsed between the time the db returns ''now'' and the mapping to a ruby value. if you track transactions you can be sure it''s the same during a transaction but the first one will be a *tiny* bit off from what the db would have done on it''s own. this is fine if you transactions only interact with other rails code but evil if you use the db, transaction, and the concept of ''now'' for some logic from other apps - it''s a race condition. - do no synchronization - let the db handle the concept for you. after all, it already knows if it''s in a transaction or not. this means NEVER calling Time::now to get the code, but doing something like def current_timestamp require ''time'' Time::parse(execute(''select current_timestamp'').first) end alias now current_timestamp instead and ALWAYS using this to obtain the string/timeobj for the current time. i''d have to read more to understand how awful things like timezone work there way into this idea though... in anycase, i like the second approach for the reason that i delegates handling of ''now'' to postgresql - so it should be consistent with what users of that db see in other applications. how does this fit into rails'' time handling in general? do all the adapters handle ''now'' - if so what is the expectation? it would argue for the first method above too...> Ara, I do not have time to put together a patch and test it at the moment, > could you?perhaps - i don''t really have any time now either - but will make an effort. it should be easy to do, i just have to collect enough information from this list to understand the big picture first. -a -- ==============================================================================| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | When you do something, you should burn yourself completely, like a good | bonfire, leaving no trace of yourself. --Shunryu Suzuki ===============================================================================
>> Looking over the code again, I think if we switched to using ''now'' as >> the >> value and modified the string_to_time function in abstract_adapter.rb >> to be: >> >> def string_to_time(string) >> return string if string.is_a?(Time) >> return Time.now if string == ''now'' >> time_array = ParseDate.parsedate(string).compact >> # treat 0000-00-00 00:00:00 as nil >> Time.send(Base.default_timezone, *time_array) rescue nil >> end> don''t think this will work - acknowledging here that i''ve only read > about > 10% of the rails source. here''s why; you can only skin this cat two > ways: > > - sychronize the postgresql adapters notion of ''now'' with that of the > database. this means knowing if you''re in a transaction or now, > and even > this is doomed to be a ''little'' wrong since there is always some > time that > has elapsed between the time the db returns ''now'' and the mapping > to a > ruby value. if you track transactions you can be sure it''s the > same > during a transaction but the first one will be a *tiny* bit off > from what > the db would have done on it''s own. this is fine if you > transactions only > interact with other rails code but evil if you use the db, > transaction, > and the concept of ''now'' for some logic from other apps - it''s a > race > condition.I wouldn''t like this approach, and since we agree on that, I''ll leave it pass. Suffice to say that the wrong layers would need to know about each other, violating encapsulation.> - do no synchronization - let the db handle the concept for you. > after all, > it already knows if it''s in a transaction or not. this means NEVER > calling Time::now to get the code, but doing something like > > def current_timestamp > require ''time'' > Time::parse(execute(''select current_timestamp'').first) > end > > alias now current_timestamp > > instead and ALWAYS using this to obtain the string/timeobj for the > current > time. i''d have to read more to understand how awful things like > timezone > work there way into this idea though...I see 3 cases to consider: 1) Reading the timestamp before the row gets saved. If you''ve got a new record, and you''re asking it for its states, we need to supply some value for the timestamp. In these cases, I would argue that Time.now is a "good enough" approximation for PG''s now(). I think some reasonably specialized contortions would be necessary to detect the start of a transaction and populate the record with that time. As its written above, if you''re working on an unsaved record outside of a transaction block, the value you receive by calling ''select current_timestamp'' would not necessarily match what gets stored in the object. So it may be no better of an approximation than Time.now. 2) Immediately after a record is saved. Our approximation is now out-of-sync with the database here, and we would do well to reload the object to match it up. Perhaps there''s some sort of notion of a volatile column that we could use here? Maybe a :reload_after_save symbol we could define in the model to trigger this behavior? This would also be nice if you''re using a last_modified column with a trigger to keep the timestamp fresh and tasty. I could go on with examples here - modified_by_user, etc. Does this already exist? 3) When reading an object by id, name, whatever. In this case everything is consistent, since we''re reading a literal timestamp out of the database. Saving this object will preserve this timestamp, which is desired.> in anycase, i like the second approach for the reason that i delegates > handling of ''now'' to postgresql - so it should be consistent with what > users > of that db see in other applications. how does this fit into rails'' > time > handling in general? do all the adapters handle ''now'' - if so what is > the > expectation? it would argue for the first method above too...Maybe we don''t have to make it a special case - perhaps just hook into a larger :reload_after_save type functionality?>> Ara, I do not have time to put together a patch and test it at the >> moment, >> could you? > > perhaps - i don''t really have any time now either - but will make an > effort. > it should be easy to do, i just have to collect enough information > from this > list to understand the big picture first.Comments? Let me see if I can get my rails dev environment back into shape and put some code where my mouth is. Regards, -- Dave Steinberg http://www.geekisp.com/ http://www.steinbergcomputing.com/
On Thu, 3 Mar 2005, Dave Steinberg wrote:>> - do no synchronization - let the db handle the concept for you. after >> all, >> it already knows if it''s in a transaction or not. this means NEVER >> calling Time::now to get the code, but doing something like >> >> def current_timestamp >> require ''time'' >> Time::parse(execute(''select current_timestamp'').first) >> end >> >> alias now current_timestamp >> >> instead and ALWAYS using this to obtain the string/timeobj for the >> current >> time. i''d have to read more to understand how awful things like >> timezone >> work there way into this idea though... > > I see 3 cases to consider: > > 1) Reading the timestamp before the row gets saved. If you''ve got a new > record, and you''re asking it for its states, we need to supply some value > for the timestamp. In these cases, I would argue that Time.now is a "good > enough" approximation for PG''s now().unless you are connecting to a remote db. for instace, in my lab some machines use utc and some mtn timezone - this would result in QUITE different results from the two. of course i think this is dealt with appropriately - but it''s thin ice to be walking... besides - i''m pretty sure anyone who does significant dealings with time, especailly intervals, will be shocked that thing are ''close'' when it comes time to generate reports...> I think some reasonably specialized contortions would be necessary to detect > the start of a transaction and populate the record with that time. As its > written above, if you''re working on an unsaved record outside of a > transaction block, the value you receive by calling ''select > current_timestamp'' would not necessarily match what gets stored in the > object. So it may be no better of an approximation than Time.now.hmmm. this is true. both cases are rotten though row = Model::new ''timefield'' => ''now'' # now mapped to a time string somehow # intense computation lasting 15 seconds... transaction do ... # timefield is totally fubar end this bring up a point: it''s really an error to substitute anything into this field. if the user load a row with ''now'' before a transaction it should STAY that way. ''now'' simply must suffice as the string representation. i know this could confuse things a bit in rails, but if a user is using postgres he EXPECTS ''now'' to be automagically transformed DURING his transaction and not before. if he tries to do date math with that value before, or expects some strftime''d output for ''now'' he''s just out of luck and must rftm. in summary in don''t think ''now'' should EVER be substituted by rails when the user has supplied it - only the db can do this correctly and at the right time.> 2) Immediately after a record is saved. Our approximation is now > out-of-sync with the database here, and we would do well to reload the > object to match it up. Perhaps there''s some sort of notion of a volatile > column that we could use here? Maybe a :reload_after_save symbol we could > define in the model to trigger this behavior? This would also be nice if > you''re using a last_modified column with a trigger to keep the timestamp > fresh and tasty. I could go on with examples here - modified_by_user, etc. > Does this already exist?maybe a column proxy object with to_s overriden?> 3) When reading an object by id, name, whatever. In this case everything is > consistent, since we''re reading a literal timestamp out of the database. > Saving this object will preserve this timestamp, which is desired.agreed.> Comments? Let me see if I can get my rails dev environment back into shape > and put some code where my mouth is.ditto. -a -- ==============================================================================| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | When you do something, you should burn yourself completely, like a good | bonfire, leaving no trace of yourself. --Shunryu Suzuki ===============================================================================
>> 1) Reading the timestamp before the row gets saved. If you''ve got a >> new >> record, and you''re asking it for its states, we need to supply some >> value >> for the timestamp. In these cases, I would argue that Time.now is a >> "good >> enough" approximation for PG''s now(). > > unless you are connecting to a remote db. for instace, in my lab some > machines use utc and some mtn timezone - this would result in QUITE > different > results from the two. of course i think this is dealt with > appropriately - > but it''s thin ice to be walking...That seems to be slightly outside the scope of the issue though - except with the possibility of Time.now *not* being in UTC if you were expecting it to be. However, upon closer examination, it would be incorrect to expect the output to be in UTC based on the queries that AR generates. Referring to http://www.postgresql.org/docs/7.4/interactive/datatype-datetime.html: "For timestamp with time zone, the internally stored value is always in UTC (Universal Coordinated Time, traditionally known as Greenwich Mean Time, GMT). An input value that has an explicit time zone specified is converted to UTC using the appropriate offset for that time zone. If no time zone is stated in the input string, then it is assumed to be in the time zone indicated by the system''s timezone parameter, and is converted to UTC using the offset for the timezone zone. When a timestamp with time zone value is output, it is always converted from UTC to the current timezone zone, and displayed as local time in that zone. To see the time in another time zone, either change timezone or use the AT TIME ZONE construct (see Section 9.8.3)." In short, unless otherwise specified, input and output timezones are assumed to be your local timezone. So Time.now would be the right approximation. A custom finder would be required to get pure UTC output times, in which case you might just want to write your own accessor to the column backed by now().> besides - i''m pretty sure anyone who does > significant dealings with time, especailly intervals, will be shocked > that > thing are ''close'' when it comes time to generate reports...Well, how often do you generate reports based on a) unsaved objects b) objects that you *just* saved? Again, if we can get some kind of :reload_after_save business going on, the question becomes moot.> row = Model::new ''timefield'' => ''now'' # now mapped to a time string > somehow > > # intense computation lasting 15 seconds... > > transaction do > ... > # timefield is totally fubar > end > > this bring up a point: it''s really an error to substitute anything > into this > field. if the user load a row with ''now'' before a transaction it > should STAY > that way. ''now'' simply must suffice as the string representation. i > know > this could confuse things a bit in rails, but if a user is using > postgres he > EXPECTS ''now'' to be automagically transformed DURING his transaction > and not > before. if he tries to do date math with that value before, or > expects some > strftime''d output for ''now'' he''s just out of luck and must rftm. in > summary > in don''t think ''now'' should EVER be substituted by rails when the user > has > supplied it - only the db can do this correctly and at the right time.I don''t agree. I think if we can have a usable approximation for the case where the record is unsaved, then are able to reload the object and make it all line up, then we''ve come to an amicable compromise. I would not want to code my apps to explicitly deal with the string ''now'' where they might normally encounter a date object. I think that''d be a step backwards in terms of making rails database agnostic. Thinking about this just a little bit more, I would argue that this should simply be a FAQ / Wiki entry. This whole issue is resolved by doing: class Foo < ActiveRecord::Base protected def after_create () reload end end Creating a new symbol to save a 4 word function seems excessive, but I''m willing to do it if there''s a desire. DHH - comments? Regards, -- Dave Steinberg http://www.geekisp.com/ http://www.steinbergcomputing.com/
Ara.T.Howard <Ara.T.Howard-32lpuo7BZBA@public.gmane.org> wrote:> so, each time default_value sees ''now'' it will call Time::now.to_s - and this > will be different each time. it may not be obvious right away since, if the > [cut] > can anyone comment on this?one way I see around this is having default_value return nil instead of Time.now, thus delegating the ''now'' call to postgresql when the activerecord gets inserted or updated. this could cause some breakage, for example code that expects new but not yet saved activerecords objects with ''now'' timestamp fields to be populated with Time.now. I think there is a division between those apps that are satisfied with rails calling Time.now and those apps that require the database to be the source of timestamps. Dave
On Thu, 3 Mar 2005, Dave Steinberg wrote:> That seems to be slightly outside the scope of the issue though - except with > the possibility of Time.now *not* being in UTC if you were expecting it to > be.<snip point conceded>> Well, how often do you generate reports based on > > a) unsaved objects > b) objects that you *just* saved? Again, if we can get some kind of > :reload_after_save business going on, the question becomes moot.neither really works. again, the problem is that not so much that you are doing reports on the unsaved objects, but that you may have contrainsts set up in the db that rely on the ''now'' field actually being ''now'' and not some ruby string plugged in instead. i know it''s hard to imagine use cases but trust me there is a whole world of them, read http://www.codeforpeople.com/lib/ruby/btpgsql/btpgsql-0.2.4/doc/ for some ideas why. i''d like to re-implement this in rails.> I don''t agree. I think if we can have a usable approximation for the case > where the record is unsaved, then are able to reload the object and make it > all line up, then we''ve come to an amicable compromise. I would not want to > code my apps to explicitly deal with the string ''now'' where they might > normally encounter a date object. I think that''d be a step backwards in > terms of making rails database agnostic.and how do you approximate this schema in rails? [ahoward@localhost ~]$ cat a.sql create table prices( id int, price float, valid_starting_at timestamp not null default ''now'', valid_ending_at timestamp not null default ''infinity'' ); insert into prices values (0, 42.0); select * from prices where valid_ending_at >= ''2005-03-03''; [ahoward@localhost ~]$ psql -f a.sql id | price | valid_starting_at | valid_ending_at ----+-------+----------------------------+----------------- 0 | 42 | 2005-03-03 20:07:08.128051 | infinity (1 row) here you''ll get the string ''infinity'' (valid postgresql for time) mapped back as the default value instead of a time object. btw, these strings could come back as well: epoch infinity -infinity now today tomorrow yesterday allballs (yes - that last one is for real) why chose ''now'' as the only one to approximate? the others come back as strings instead of a time objects under the current mapping anyhow - yet all but the infinities can be. (and maybe they should be) also, even if you do some sort of reload after insert the current setup totally blows up if you do price_beer = Price::new # using default of Time::now here! price_wine = Price::new ''valid_starting_at'' => ''now'' # but not here! # begin transaction # insert price_beer # caluclate the distance to the region producing your wine - takes 1 second # insert price_wine now the price of beer and the price of wine will have different valid_starting times even though both were inserted under a transaction with a time of ''now''! later, when generating the report of which prices you updated last week - you''ll miss one. the problem is not the approximation in ruby-land, it''s that the value used in subsequent inserts from ruby-land into the db is not the one specified by the schema nor one specified by the user/code - it''s some random time that''s ''pretty close'' to those ones. i agree that in 97% percent of case it''ll be pretty damn close - but we all those kind of bugs are days * number_of_users in the unmaking.> Thinking about this just a little bit more, I would argue that this should > simply be a FAQ / Wiki entry. This whole issue is resolved by doing: > > class Foo < ActiveRecord::Base > protected > def after_create () reload end > endi suppose one answer is, in fact, to say : if you want it right specify your times as ''now'' and do not rely on default mappings... you still have to code around the other strings though... previously i''ve handled infinite time using class Time INF = INFINITY = 1.0 / 0 NINF = NEGATIVE_INFINITY = -1.0 / 0 EPOCH = Time.at(0) class << INFINITY include Comparable def <=> o;id == o.id ? 0 : 1;end end class << NEGATIVE_INFINITY include Comparable def <=> o;self.id == o.id ? 0 : -1;end end def coerce(x) case x when Float return [x, to_f] when Integer return [x, to_i] else super end end end so at least i could have an object that compared larger/smaller than all other times - the to_s method might be nice to override too...> Creating a new symbol to save a 4 word function seems excessive, but I''m > willing to do it if there''s a desire. DHH - comments?at this point in half-agreement with Dave Lee; i don''t think ''now'' should come back as a string - rather it should come back as a string like the rest of of the special time values. this is the simplest solution that is totally correct IMHO. hopefully i''ve made my point clear enough at this point and will defer to the powers that know more. kind regards. -a -- ==============================================================================| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | When you do something, you should burn yourself completely, like a good | bonfire, leaving no trace of yourself. --Shunryu Suzuki ===============================================================================
>> Well, how often do you generate reports based on >> >> a) unsaved objects >> b) objects that you *just* saved? Again, if we can get some kind of >> :reload_after_save business going on, the question becomes moot. > > neither really works. again, the problem is that not so much that you > are > doing reports on the unsaved objects, but that you may have > contrainsts set up > in the db that rely on the ''now'' field actually being ''now'' and not > some ruby > string plugged in instead. i know it''s hard to imagine use cases but > trust me > there is a whole world of them, read > http://www.codeforpeople.com/lib/ruby/btpgsql/btpgsql-0.2.4/doc/ for > some > ideas why. i''d like to re-implement this in rails.You''re right here, I lost track while writing the original email. I agree that we need to delegate the permanent definition of ''now'' to PostgreSQL. What if there was a way to supply ''Time.now'' to the ruby world and the string ''now'' to the database (covering the unsaved object case). Then if we reload newly saved objects, we''d be completely in sync.> valid_starting_at timestamp not null default ''now'', > valid_ending_at timestamp not null default ''infinity'' > ); > insert into prices values (0, 42.0); > select * from prices where valid_ending_at >= ''2005-03-03'';Yep, right now there''d be no way. That''s actually a nice way of doing it - I had merely used nulls previously.> [ahoward@localhost ~]$ psql -f a.sql > id | price | valid_starting_at | valid_ending_at > ----+-------+----------------------------+----------------- > 0 | 42 | 2005-03-03 20:07:08.128051 | infinity > (1 row) > > here you''ll get the string ''infinity'' (valid postgresql for time) > mapped back > as the default value instead of a time object. btw, these strings > could come > back as well: > > epoch > infinity > -infinity > now > today > tomorrow > yesterday > allballs > > (yes - that last one is for real)While reading through the docs yesterday, I literally laughed out loud at the last one. We could provide some ruby-equivelant constants for most of those, obviously the tricky ones are now, and +/- infinity. For the others, a patch would be easy.> why chose ''now'' as the only one to approximate? the others come back > as > strings instead of a time objects under the current mapping anyhow - > yet all > but the infinities can be. (and maybe they should be)Agreed. When I came to the code, they weren''t there, and I wasn''t familiar with them, so I just handled ''now'' as best I could. I think they come back as strings more for accidental reasons than intentional ones.> also, even if you do some sort of reload after insert the current > setup totally > blows up if you do<snip>> now the price of beer and the price of wine will have different > valid_starting > times even though both were inserted under a transaction with a time > of ''now''!Yep - again, I lost track of that point in my last mail. The database definitely needs to receive the string ''now''.> i suppose one answer is, in fact, to say : if you want it right > specify your > times as ''now'' and do not rely on default mappings... you still have > to code > around the other strings though... previously i''ve handled infinite > time > usingAny ideas how we could handle this gracefully? In my own code I''ve dealt with the inability of ruby''s Time object to just specify a time without a date, so if we''ve got several problems with this object, perhaps we look towards supplying a more full-featured one. Ideas?> at this point in half-agreement with Dave Lee; i don''t think ''now'' > should come > back as a string - rather it should come back as a string like the > rest of of > the special time values. this is the simplest solution that is totally > correct IMHO.Yes, but the least sublime. At the very least, we should recognize the other special keywords and provide Time object equivalents for them and return the others as strings. If we do return ''now'' as a string, we ought to update the helpers so that they can deal with it.> hopefully i''ve made my point clear enough at this point and will defer > to the > powers that know more.Few seem to be chiming in. I''ll try and post a patch with the easy keywords properly adjusted, and I''ll try and play around with a split representation for now. Regards, -- Dave Steinberg http://www.geekisp.com/ http://www.steinbergcomputing.com/
On Fri, 4 Mar 2005, Dave Steinberg wrote:> What if there was a way to supply ''Time.now'' to the ruby world and the > string ''now'' to the database (covering the unsaved object case). Then if we > reload newly saved objects, we''d be completely in sync.that''d be pretty easy: def default_values value ... when /now/ now = Time::now class << now def bi_polar_to_s ''now'' end end now ... end ... def rails_obj_to_rdbms_mapping value meth if value.respond_to? ''bi_polar_to_s'' ''bi_polar_to_s'' ... ... value.send meth end so conceptually mark objects that that need this split to_s functionality - one to_s in rails-land and another in db-land. i don''t know where the second half takes place or my example might make more sense but maybe it''s clear enough?> While reading through the docs yesterday, I literally laughed out loud at > the last one. We could provide some ruby-equivelant constants for most of > those, obviously the tricky ones are now, and +/- infinity. For the others, > a patch would be easy.to really handle +/- infinity i think you need to extend the built in time class to be able to handle two special singleton objects with appropriate comparisson semantics (alwasy less/greater than every other time except themselves) AND a special string representation - maybe ''0000-00-00 00:00:00-00'' and ''9999-99-99 99:99:99-99'' since these are practically impossible... everytime i''ve tackled this before i''ve given up though. time can be so tricky to manage (no pun intended).> Agreed. When I came to the code, they weren''t there, and I wasn''t familiar > with them, so I just handled ''now'' as best I could. I think they come back > as strings more for accidental reasons than intentional ones.fair enough.> Any ideas how we could handle this gracefully? In my own code I''ve dealt > with the inability of ruby''s Time object to just specify a time without a > date, so if we''ve got several problems with this object, perhaps we look > towards supplying a more full-featured one. Ideas?maybe a TimeStamp object? this might be a really clean solution - but a bit of work and thinking...>> at this point in half-agreement with Dave Lee; i don''t think ''now'' should >> come back as a string - rather it should come back as a string like the >> rest of of the special time values. this is the simplest solution that is >> totally correct IMHO. > > Yes, but the least sublime. At the very least, we should recognize the > other special keywords and provide Time object equivalents for them and > return the others as strings. If we do return ''now'' as a string, we ought > to update the helpers so that they can deal with it.i agree that it would be nice to give something other than a string and now agreed that it''s o.k. to have approximations at the presentation (rails-to_s) level - so long as the db stays consistent in the end. this is a ''wiki-able'' oddity most people should be able to grasp...> Few seem to be chiming in. I''ll try and post a patch with the easy keywords > properly adjusted, and I''ll try and play around with a split representation > for now.o.k. then - i really need to read some more source before i can suggest any objectification of the problem. i''ve got to do some rails stuff this weekend so i''ll poke around then and mull some more. cheers. -a -- ==============================================================================| EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | When you do something, you should burn yourself completely, like a good | bonfire, leaving no trace of yourself. --Shunryu Suzuki ===============================================================================
Dave Steinberg <dave-dated-1110561907.e66a90-xviZR3pNp+Yxsqv6Oivclw@public.gmane.org> wrote:> What if there was a way to supply ''Time.now'' to the ruby world and the > string ''now'' to the database (covering the unsaved object case). Then > if we reload newly saved objects, we''d be completely in sync.we could subclass String and then have special case handling for this subclass in AbstractAdapter#quote: class Foo < String def initialize object super object.to_s end end in default_value: return Foo.new(Time.now) if value =~ /^\(''now''::text\)::(date|timestamp)/ in AbstractAdapter#quote when Foo, NilClass then "NULL" this line would need to be moved above the ''when String'' clause. I''m not sure what the right name for Foo would be, maybe EphemeralValue, PlaceHolderValue, RailsApproximation, or ForecastValue. this would allow the value to be a string, but tagged so that it can be handled specially. Dave
I have an association in Class Pe has_many: territories Now when I write @pe.territories.find_all I get the collection of all territories associated with instace @pe. But @pe.territories.find_all("lord_id = '''' OR lord_id IS NULL") gives me ALL territories, independet of being associated with @pe or not!!!! Territory.find_all("(lord_id = '''' OR lord_id IS NULL) AND politicalentity_id = #{@pe.id}") gives the right result. Am I doing something wrong, or is this a bug? Thanks, Pedro
Gents, I realized that since I''m not up to .10.1 yet, nor have I got Ruby 1.8.2 installed, I''m going to have to abstain from providing patches until then. Gotta be able to run the test suite before I can submit a patch. Regards, -- Dave Steinberg http://www.geekisp.com/ http://www.steinbergcomputing.com/