Skip to content
This repository

Modified generated Gemfile to allow patch versions of Rails. #6610

Closed
wants to merge 1 commit into from

11 participants

Philip Arndt Steve Klabnik Santiago Pastorino Rafael Mendonça França Michal Papis Piotr Sarnacki Robert Pankowecki Piotr Niełacny Yehuda Katz David Sommers Robert Evans
Philip Arndt
parndt commented June 03, 2012

Fixes #6604 which was a great idea by @mpapis

This change allows, for example when generating an application using Rails 3.2.5, the application to use 3.2.5 -> 3.2.x but not 3.3 or greater and not less than 3.2.5.

I believe that this is a good idea given that security issues are often fixed with patch releases and that it is safe to do so as these versions are tested for regressions which, when found, are solved with a subsequent release.

I couldn't find any tests that are related to this change and all railties tests passed (eventually).

Thanks :-)

Steve Klabnik
Collaborator

I'm naturally a :+1: on this, but ~> is really intended for SemVer style versioning, and Rails doesn't really do that... so I'm pretty neutral.

Santiago Pastorino
Owner

:-1:

Rafael Mendonça França
Owner

I'm :-1: with this. We try to not add incompatible changes in patch versions but sometimes it occurs because the users can be using a bugged behavior assuming that it is correct. So I prefer a more conservative approach.

If the users want to use the ~> they can change in their Gemfile.

Michal Papis
mpapis commented June 03, 2012

To make any difference users would have to run bundle update rails or bundle update, this change would not affect any bundle install.

For users that use bundler properly it would be only triggered on bundle update rails - which would be an conscious decision for them.

Piotr Sarnacki
Collaborator
drogus commented June 03, 2012

From my experience, changing rails version in most apps is not a quick "update and forget process". Usually you need to see if everything works as expected and if extensions that you use don't break. That's why I prefer to keep strict version.

Michal Papis
mpapis commented June 03, 2012

Sticking with one version is a bad thing, we encourage people to upgrade to at least latest patch level of ruby, to test their apps against all the rubies, but in the same time we tell them to stick with one rails version, at least add a comment to update it once in a while, would it be a solution?

Rafael Mendonça França
Owner

Keeping the strict version are not saying that the people should not upgrade the Rails version, it is saying to people that if they want to upgrade the version they need to change the Gemfile.

For me this is a conscious upgrade. This avoid acidental upgrade when the user run bundle update without pass the gem name.

As @drogus said, upgrade the rails is more than install the newest version. Gem author can use some private API that changed in the newest release or users can rely in bugged behavior, so I think that upgrade the rails version should be always conscious.

Philip Arndt parndt closed this June 03, 2012
Philip Arndt parndt reopened this June 03, 2012
Philip Arndt
parndt commented June 03, 2012

(accidentally clicked the 'close and comment' sorry)

If gem authors use private APIs (myself included) then it's kind of their own fault don't you think? [edit: this doesn't make much sense - clarified in the last paragraph below]

It's not like developers call bundle update in production (right?) .. here's how I normally do it:

  • Specify ~> 3.2.5 in Gemfile
  • bundle update rails
  • run tests locally
  • commit Gemfile.lock change to a new branch and run against CI where possible
  • problems found -> fix problems
  • deploy to production

If you run a normal bundle install then the version won't upgrade.. which means when you do run bundle update you're in a state where you're fully prepared to mitigate any issues that arise.

If you're a gem author then this change is irrelevant to you as you'll be specifying a Rails version dependency in your .gemspec file.

Rafael Mendonça França
Owner

Another reason to use strict version. If you have installed Rails 3.2.3 and run rails new new_application you will get the a new application running the Rails 3.2.5. I don't see this as a correct behavior.

Philip Arndt
parndt commented June 03, 2012

@rafaelfranca our opinions differ as I see that as a benefit; you get to start with the latest patch level already installed. Imagine not knowing there was a security update -- this way you get a de facto notification that you weren't running the latest patch code.

Robert Pankowecki
paneq commented June 04, 2012

+1 from me. I totally agree with @parndt .

Piotr Sarnacki
Collaborator
drogus commented June 04, 2012

Imagine not knowing there was a security update -- this way you get a de
facto notification that you weren't running the latest patch code.

If your application is tested enough to allow changing versions without thorough check, just change the Gemfile entry. The sad reality is that a lot of apps touch internal stuff or depend on plugins that use internals.

@paneq @parndt Would you say that majority of rails apps can be upgraded without any problems? My experience tell me something completely different.

Steve Klabnik
Collaborator

Agree with @drogus. So many apps that mess with things that they shouldn't...

Michal Papis
mpapis commented June 05, 2012

/me sad

this should be done only for new apps - those that are not yet broken

It seams very bad from both sides:

  1. rails changing APIs (internal or not) when releasing next patch version - ( p 2. http://semver.org/ )
  2. rails not exporting good enough APIs so people hack using internals - wasn't rails3 supposed to solve that problem, so gem/plugin authors can finally write good code?

I have an impression that you gave up and prefer to stick to older rails patch level instead of promoting fixed version - which fixes security issues (because that's what you do for every patch version increase).

Rafael Mendonça França
Owner

First, Rails doesn't follow semver.

Second, no one is telling that people can upgrade to the next version, we only prefer to stick the rails version in the Gemfile to the people don't update the rails by mistake when run bundle update.

And finally, we avoid changes in the API in patch version but sometimes people can use bugged behavior as correct and they application can be broken with a patch upgrade. So even with a stable API a patch update can broke the application.

Piotr Niełacny
LTe commented June 05, 2012

Rails doesn't follow semver.

Maybe should start?

Piotr Sarnacki
Collaborator
drogus commented June 05, 2012

rails not exporting good enough APIs so people hack using internals - wasn't rails3 supposed to solve that problem, so gem/plugin authors can finally write good code?

Please note that situation since Rails 3 is much better than in 2.x times and there is a lot of good APIs that can be used by gem developers (or application developer, if they need something other than defaults). However, it's virtually impossible to predict every case of framework extension. If there is anything that can't be done with current API, people should open issues (or better pull requests).

Also, I was not trying to say that people use rails internals, mainly because rails doesn't provide good APIs. It can be the case, but most of the time I've seen code that tried to be "too clever" in my opinion - a lot of things can be achieved in many different ways and often code that touch internals can be refactored into proper implementation that doesn't do it.

I have an impression that you gave up and prefer to stick to older rails patch level instead of promoting fixed version - which fixes security issues (because that's what you do for every patch version increase).

I haven't given up. I think that people should be on the latest stable release. The thing is, changing Gemfile will not force people to upgrade. I've seen a lot of apps that can't be upgraded because a lot of things breaks after upgrading to next version - in such situation they will not upgrade, they will hardcode current version in Gemfile anyway.

The other thing is, I see a little problem with your reasoning. You say that people will upgrade version only after running bundle update rails or bundle update intentionally. And in the same time you say that having the number hardcoded in Gemfile will keep people from intentional upgrades.

I assume that given that most rails apps are hard to upgrade painlessly and ~> operator in Gemfile, people will just avoid bundle update until they explicitly want to upgrade, which will have similar effect that hardcoding version - in both situations upgrade is done when needed. The difference is that if you run bundle update by mistake, you may end up with broken production application.

Steve Klabnik
Collaborator

Everyone loves SemVer until they want a breaking change.

(I would like Rails to follow SemVer too, but it would be a MASSIVE undertaking)

Robert Pankowecki
paneq commented June 05, 2012

It seems that the only reason for rejecting this patch is the fear that people may run bundle update and surprisingly update rails. Wow, why don't we prevent them from overwriting Ruby methods, oh wait... People can harm themselves in thousand different ways when executing wrong commands. That's why we have SCM tools like git, don't we ? If you executed bundle update you are already trying to update in 1 step hundreds of gems and that probably won't work.

Anyway, no one is crazy enough to just update and deploy to production right ? We do run tests before doing deploy. If I update rails, or any other gem in that matter and my tests are passing then I choose to believe that I can deploy it. It is equally possible that there was a unknown / untested bug in previous Rails version as that it is in the updated one. I choose to believe in progress and that rails is getting better and that upgrading often is a good thing.

Let's think about 2 usecases:

a) Someone executed bundle update (accidentally or not). Current status: All gems marked with ~> except rails are getting upgraded. Good luck with that. With merged pull request: All gems marked with ~> are getting upgraded. If tests are passing then IMHO the application is working fine. If tests don't pass then I can just revert changes with git

b) Someone executed bundle update rails. Current status: rails is not going to upgrade. Probably not what I wanted right? With merged pull request: rails is upgraded to newest version with possibly some security updates. Good, that's what I wanted obviously.

Robert Pankowecki
paneq commented June 05, 2012

@drogus - I think we should focus on usecases when people execute commands intentionally, properly and with knowledge about what they are doing. I also think that they can easily test the changes and revert in case they don not like the result of their accidental command execution. Please remember that the required version of gems are hardcoded in Gemfile.lock. Gemfile is about how I want to be able to upgrade my application in future. Which gem versions I believe could cooperate together.

Yehuda Katz
Owner
wycats commented June 05, 2012

We sort of do follow semver, with a shifted version as Ruby does.

Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced. A bug fix is defined as an internal change that fixes incorrect behavior.

Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is introduced to the public API. It MUST be incremented if any public API functionality is marked as deprecated. It MAY be incremented if substantial new functionality or improvements are introduced within the private code. It MAY include patch level changes. Patch version MUST be reset to 0 when minor version is incremented.

Patch versions of Rails do not introduce backwards-incompatible changes intentionally and do not usually add new features, except as necessary for security fixes or deprecations. That makes patch levels in Rails more like minor versions. Rails has no version number similar to patch versions. Ruby uses a similar scheme, but uses "patch level" versions for this purpose.

Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced to the public API. It MAY include minor and patch level changes. Patch and minor version MUST be reset to 0 when major version is incremented.

Rails minor versions (3.0 => 3.1, 3.1 => 3.2, etc.) serve as major versions for Semver purposes. In general, we try to avoid introducing breaking changes in minor versions, but don't promise no breaking changes. In general, breaking changes in minor versions are paired with deprecation notices in a teeny version of the prior minor version.

Rails major versions usually make substantial breaking changes. The primary difference between minor and major releases in Rails is the magnitude of the breaking changes. Changes made in minor versions are small and should not require large-scale application changes, unless required for security fixes. Changes made in major releases often do require large-scale application changes (think XSS protection in Rails 3.0 and the Ruby 1.9 requirement in Rails 4.0).

In general, the first minor release of a new major release maintains as much backwards compatibility as possible with the last release, with the removal of that support in the .1 (or later) release. For example, Rails 3.0 included support for the Rails 2.3 Router, ActionMailer syntax, ActiveRecord query API. Rails 3.1 and 3.2 removed much of this support.

From that perspective, this change should be fine. That said, I'm unsure what this adds:

  • Before, updating to a new version required making a change to the Gemfile and running bundle install. This preserves conservative updating semantics and involves an intentional choice to use a particular Rails version.
  • After, updating to a new version means using bundle update rails. This does not preserve conservative updating semantics (it can result in an unnecessary update to a Rails dependency like Rack, even the dependency is shared with another gem that is not being updated).

As far as I can tell, the tradeoff is "having to know what version of Rails is the latest version" vs. "overeager updating semantics". Why do people think that breaking conservative updating semantics are worth it?

Robert Pankowecki
paneq commented June 05, 2012

@wycats - Changing rails ~> 3.2.4 to rails ~> 3.2.5 and running bundle install instead of keeping rails ~> 3.2.4 and running bundle update rails results in conservative update or not ? Will it prevent unnecessary update to ex. Rack ?

Yehuda Katz
Owner
wycats commented June 05, 2012

Anytime you run bundle update X, child dependencies of X are unlocked in the resolution step.

If you modify a dependency in the Gemfile and run bundle install, only the gems that you modified and dependencies of that gem that are not shared by other gems are unlocked.

When you run bundle update, all gems are unlocked.

Robert Pankowecki
paneq commented June 05, 2012

In other words, After this change, you can still have the same behavior as Before if you follow the exact same steps. Right?

Rafael Mendonça França
Owner

For my understanding, wrong. After this patch if you run bundle install it will not update the rails version, what means that you need to run bundle update rails.

Rafael Mendonça França
Owner

For my understanding, wrong. After this patch if you run bundle install it will not update the rails version, what means that you need to run bundle update rails.

David Sommers

Currently ~> is used with sass-rails and coffee-rails. I always change rails to use it as well. For consistency, why not change to match? I use bundle/gem to reveal to me the version running (or grep Gemfile.lock). I don't read the Gemfile.

It seems that bundle update rails should, by default, update rails. One less thing to explain.

Steve Klabnik
Collaborator

For consistency, why not change to match?

Different gems have different upgrade needs and policies.

Michal Papis

From http://weblog.rubyonrails.org/2012/8/3/ann-rails-3-2-8-rc2-has-been-released/:

IMPORTANT

We are removing all the deprecation warnings that we introduced in 3.2.x. We have decided to stop introducing API deprecations in all point releases going forward. From now on, it'll only happen in majors/minors.

Is it step towards semantic versioning and allowing this pull request to be merged?

Steve Klabnik
Collaborator

It's not an explicit step towards semver, but it is a step towards being a bit more consistent about what happens when.

Rafael Mendonça França
Owner

I don't think so. Also 3.2.7 was a huge example how a patch version can break applications that rely in bugged behavior.

Robert Evans

I'm :thumbsdown: on this. If you create a new app with whatever version of rails you have installed on your machine, it should use that version - principle of least surprise, IMHO.

If you want to follow SemVer (which is great), nothing stops you from editing the Gemfile and doing so.

Steve Klabnik steveklabnik closed this September 11, 2012
Steve Klabnik
Collaborator

Okay. After this discussion, I think the potential for breakage is too high. If you want this behavior, it's two characters to change in your Gemfile. I don't think it's responsible for us to make this change. We're not perfect, and sometimes people rely on bugged behavior as well.

Thanks for the idea, though!

Philip Arndt

Yep - happy to put this one to bed seeing as people are fairly divided on the issue. Thanks for taking part, everyone!

Philip Arndt parndt deleted the branch August 11, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Jun 03, 2012
Philip Arndt Modified generated Gemfile to allow patch versions of Rails.
Fixes #6604
72e2302
This page is out of date. Refresh to see the latest.
2  railties/lib/rails/generators/app_base.rb
@@ -151,7 +151,7 @@ def rails_gemfile_entry
151 151
           GEMFILE
152 152
         else
153 153
           <<-GEMFILE.strip_heredoc
154  
-            gem 'rails', '#{Rails::VERSION::STRING}'
  154
+            gem 'rails', '~> #{Rails::VERSION::STRING}'
155 155
 
156 156
             # Bundle edge Rails instead:
157 157
             # gem 'rails', github: 'rails/rails'
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.