the tzinfo version packaged with rails 2.1.2 is incorrect and missing
some files. If you compare the version stored in activesupport/lib/
active_support/vendor/tzinfo-0.3.11 with a fresh gem install of
tzinfo-0.3.11, the activesupport-2.1.2 version is missing all the
country_code files.
This means that if the rails version is loaded up, calling
TZInfo::Country.get('US').zones
fails, while if the standard gem version is loaded, it works.
I was explicitly setting, in environment.rb
config.gem "tzinfo", :version => '0.3.10'
but rails 2.1.2 sets 0.3.11, and because I didn't have that gem
installed on my system, it loaded the broken one from
activesupport-2.1.2.
The way to get all of this to work is to install the 0.3.11 gem and
change my environment.rb file to require the 0.3.11 version, and then
it loads up the full gem version and bypasses the bad rails 2.1.2
version. But this definitely doesn't seem like the correct behavior,
starting with the bad vendorized tzinfo-0.3.11 gem in
activesupport-2.1.2.
The bundled tzinfo is a slimmed-down version that only includes the
classes and zone definitions necessary to support
ActiveSupport::TimeZone. This chops ~2.8MB from the size of tzinfo,
and hundreds of files, so it seems worth it.
But as far as trying to require a complete version of the gem that's
older than the bundled version -- indeed, that wouldn't work. I agree
it's confusing, given that you've declared the explicit version of
tzinfo via config.gem.
Maybe we could be smarter about how we require bundled libraries in
activesupport/lib/vendor.rb -- maybe add logic so that we don't
clobber existing gem requirements?
By bundling tzinfo, everything works out of the box -- if you freeze
rails into vendor, you can then deploy anywhere, even on boxes that
don't have rails or tzinfo installed.
Isn’t there a method of freezing not just rails, but all gems your project uses?
Seems to me that if you’re dealing with an uncooperative host, that’s the route you want to go – those of us with cooperative hosts would probably rather manage things with gems. Often, that’s unavoidable – rmagick, for example.
Certainly seems odd to be doing this in a support library.
Right, but why is tzinfo special? Because it is the only “non-rails” dependency for rails itself. Seems like the root cause of the problem is that rails freeze command is broken, because it does not freeze the entire dependency graph of rails, which includes tzinfo. Instead, the rails freeze command should freeze whatever version of the tzinfo gem is specified by the current version of activesupport. Then, you get all the benefits and no problems:
Rails is not packaging a hacked version of tzinfo
Since tzinfo is not bundled, you don’t need to use a hacked smaller version, you can just depend on the real gem
People who want to manage tzinfo via gems using whatever version they want can do so (which is the original bug report here)
People who want to freeze rails will automatically get the real, correct version of tzinfo frozen as well - and shouldn’t care if this is big, because people who freeze gems will have ginormous apps regardless…
Please keep in mind, you *can* manage the full Tzinfo gem via
config.gem -- the bug you identified only occurs when you try to
require a version that's older than the bundled one.
Also, Tzinfo is not the only non-Rails dependency: see the vendor
directories in ActionMailer, ActionController and ActiveSupport. Do
you suggest that Rails unbundle TMail, Builder, XmlSimple, etc., and
add them as dependencies to the rails gem?
Also, Tzinfo is not the only non-Rails dependency: see the vendor
directories in ActionMailer, ActionController and ActiveSupport. Do
you suggest that Rails unbundle TMail, Builder, XmlSimple, etc., and
add them as dependencies to the rails gem?
I would, unless they have patches which haven't made it upstream. And in
that case, I'd break them out into rails-tmail, rails-builder, etc.
Assuming gem freezing works, what is the reason not to do that?
If gem freezing is broken, why not fix it?
That's a real question -- there may be a good reason. I'm new here.
The bundled gems already favour installed gems if user's have them.
The rationale for bundling them is that they're not a dependency to
use *all* of rails, just a small piece of functionality (e.g. the
memcache cache store).
There's no practical benefit to be gained by changing this policy, the
new config.gems code will already provide information to people who
make this same 'mistake' again.
Also, Tzinfo is not the only non-Rails dependency: see the vendor
directories in ActionMailer, ActionController and ActiveSupport. Do
you suggest that Rails unbundle TMail, Builder, XmlSimple, etc., and
add them as dependencies to the rails gem?
I would, unless they have patches which haven't made it upstream. And in
that case, I'd break them out into rails-tmail, rails-builder, etc.
Assuming gem freezing works, what is the reason not to do that?
If gem freezing is broken, why not fix it?
That's a real question -- there may be a good reason. I'm new here.
The bundled gems already favour installed gems if user's have them.
The rationale for bundling them is that they're not a dependency to
use *all* of rails, just a small piece of functionality (e.g. the
memcache cache store).
There's no practical benefit to be gained by changing this policy, the
new config.gems code will already provide information to people who
make this same 'mistake' again.
Geoff, it sounds like there is not an easy solution except perhaps if
you bundle a version like 0.3.11 but rails *requires* 0.3.9, use
~>0.3.9 for the config.gem version rather than always incrementing it
to 0.3.11. But that could create additional issues like missing a
dependency, etc.
If I'm the only one who was bit by this issue, then so be it. But if
it keeps coming up, putting the full gem (with the extra 2.6 megs and
hundreds of files; yes it is a beast!) into vendor/ doesn't seem to be
all that bad, in this day and age of broadband
It isn’t just the download bandwidth, it’s moving around and storing that extra 2.6 meg for every checkout, branch, deployment, release, and backup for every rails app, everywhere, forever, not to mention the few extra split-seconds on every full-project search. CPU, diskspace and bandwidth are cheap, but not infinite, and it adds up when you think of it that way. That’s why I prefer to freeze nothing
If ActiveSupport required an older version than what was bundled,
you'd run the risk of requiring an older version of the gem that
happened to be installed on your system, even if you didn't explicitly
declare it via config.gem.
I do think we should respect a version explicitly specified via
config.gem, even if it's an older version than the bundled one (which
we're not doing right now.) Or at least give feedback that we're not
respecting the user's declared wishes. I don't know if this would even
be possible -- we'd have to somehow introspect the gem requirements, I
guess.
Fyi, Rails should be compatible with any tzinfo version in the 0.3.x
series (and possibly the 0.2.x series, though I haven't tested this
recently.) For the most part, the version upgrades are just changes to
tzdata; there haven't been any changes to the api in 0.3.x that would
affect compatibility.
The caveat with this setup would be, the GMT offsets that appear in
the time_zone_select could be out of sync with the tzinfo version
you're using. Which would be kind of odd.
Maybe this is an argument for not allowing older versions of tzinfo to
be used?
If ActiveSupport required an older version than what was bundled,
you'd run the risk of requiring an older version of the gem that
happened to be installed on your system, even if you didn't explicitly
declare it via config.gem.
that actually isn't true. I had tzinfo 0.3.10 installed using rails
2.1.1. that rails version shipped with tzinfo-0.3.9, but it correctly
used my config.gem specification and used the 0.3.10 version. The
issue arose because I migrated to rails 2.1.2, which came with a
partially bundled tzinfo-0.3.11, used that version and ended up
breaking my application (thankfully not in production; love those
tests!).
Chad, I agree with your point about bundling, but at the risk of
beating a dead horse, my vote would be to either bundle the full gem
(instead of a partial one with broken dependencies) OR do not bundle
and just have dependencies (like active-record does on a db-specific
gem).
...seems to work, given my limited testing. With this setup, you can
effectively have access to the full gem, and updates to the bundled
version won't break it. Also slims down your app repository a bit,
since you don't have to duplicate tzinfo files that are already
bundled in AS.
I was just bikeshedding about the dubiousness of bundling a hacked version of a dependency gem in another gem, and adding code manage the resulting problems. I didn’t actually have a personal problem (with tzinfo). Thanks, though