In my Gemfile, I'm including a gem that has a .gemspec that uses the pessimistic operator ~> to specify a version of the gem. However, I need to use a newer version of the gem. In my case I'm using spree 3-0-stable that has activemerchant set to '~> 1.47.0' https://github.com/spree/spree/blob/3-0-stable/core/spree_core.gemspec#L22 but I need use active merchant '~> 1.59.0'
I tried to specify version 1.59.0 in my Gemfile but bundle complains with:
You have requested:
activemerchant ~> 1.59.0
The bundle currently has activemerchant locked at 1.47.0. Try running
bundle update activemerchant
If you are updating multiple gems in your Gemfile at once, try passing
them all to bundle update
But the command bundle update activemerchant will only update to 1.47.x.
What's the rails-y way of accomplishing this? Aside from forking spree myself and updating the .gemspec? Obviously updates to the activemerchant gem might break the spree gem. But I can test with my app.
The maintainers of Bundler have recommended forking the relevant gem, then making a PR back onto the gem. Then link directly to the branch in that PR in your Gemfile. This encourages the community to rally around a solution.
I've documented the process in detail here: https://github.com/rubygems/rfcs/pull/13#issuecomment-770416467
You can't do it, the rubygems system doesn't allow that. You have to file an issue for the upstream gem dependency, and ask them to loosen their requirements.
It may be that the version of activemerchant you want actually won't work with the version of spree you want, it will break it. If so, spree code would have to be fixed to work with the new version of activemerchant. Or, it could work fine with the version you want, the restriction in spree is accidentally unneccesarily strict, in which case the spree gemspec would just have to be changed to allow it.
But there's no way for you to override it without changing the spree gemspec.
You could make your own fork of spree in which you change the gemspec -- but without knowing whether or not spree will really work with the version of activemerchant you want, that could be dangerous. And now you're on your own fork, so you won't be able to upgrade to new versions of spree without merging in their changes to your fork, etc.
Another thing is, it's a bit odd to be running off a spree 3-0-stable branch, instead of an actual released version of the gem. But I'm not familiar with spree's release management practices, perhaps this is what they encourage? At any rate, changing this probably won't fix your problem.
If your app is relatively new or simple, you could consider switching from spree to solidus, a fork of spree. Solidus forked off at spree 2.x though, so migration from spree 3.x might not be straightforward, especially if your app is established and somewhat complex. Although the solidus_core gem is also locked to activemerchant ~> 1.48.0, so it also won't allow anything but activemerchant 1.48.x. The solidus team is pretty responsive on their Slack channel, if you wanted to ask them what's up with that, if they know if later versions of activemerchant will work, if the dependency can be loosened. I have found the solidus maintainers to be very responsive, and likely to be interested in allowing later versions of activemerchant if it's feasible to do. I'm not familiar with the current Spree team and how they communicate with users (if they have a slack, or listserv, or are responsive on github issues, or what), but you could of course have the same conversation with them.
Related
I have a rails project that have alot of gems, whitch works on server, few days ago I decide to update my project to latest version of rails and gems then I found some gems in my project depricated and I have to refactore my code.
Then i found does it possilbe to change some configuretions in my rails project to declare me when should I update gems in gemfiles or i have to check my gemfile manually to be sure my project up to date?
I google my idea but nothings found useful witch can help me
Not sure this is possible by rails configuration. rails or gems used will usually log deprecated messages if they intend to deprecate any feature.
however, there are other free apps that can do similar things like https://depfu.com/ which will depend on how you set your configuration, open a PR with gems that need updates
there is also https://dependabot.com/ by Github which also has the power (if your project is on any git platform) to show you messages on which gem needs a security update or is being deprecated in the security tab
I would like to add this change https://github.com/rails/rails/commit/94584c2510743a45d9030d1b94dd33a074518b17 to release/version 6.0.3.3. How I can do this? Is it smart idea to do so? It sounds for me like I would like to cherry pick this change?
Do as follows:
Create rails fork of the unreleased version that you need
In your Gemfile, add gem 'rails', git: 'https://github.com/you/your-rails-fork'
Run bundle
When it is released, restore gem 'rails' in your Gemfile
It is not a bad idea to do so, as long as:
It actually gets released at some point and you get back to the community-kept official version when it does (for the security reasons mostly).
You don't introduce any custom changes in the forked repository - if you do, you might get in trouble when trying to get back to official rails.
I'm presently using
gem 'rails', '~> 5.0.0'
in my Gemfile.
I just learned of a different way to specify a Rails branch, which is:
gem 'rails', github: "rails/rails", branch: '5-0-stable'
Is there a best practice to include Rails in a Gemfile? Why would you use one way over the other?
gem 'rails', '~> 5.0.0'
Uses what is called pessimistic versioning. The so called squiggly arrow means that it will use any new minor version in 5.0.X this means that you still get bugfixes but can be pretty sure the library won't suddenly change on you.
~> 5.0.0 is equivalent to >= 5.0.0 <5.1.
Linking a gem directly to a github repo is only really a good idea if you want to be on the bleeding edge or if an major issue or incompatibility exists in the latest release but is fixed in the master or another branch/tag. Another common case is where you need to fork a gem.
Often the case is that you want to use gem A, but the latest release of gem B is incompatible with A which often happens right after a major version is released.
To link all your gems directly to their master branches would be very trying for your sanity. Bundler can't actually resolve the versions there so will be no help for doing dependency resolution.
There's no best practice that I know of.
The stable branch of rails changes constantly, it just tries to have no bugs. Using such a branch might be a good idea if you know that you want your app to target the next version of Rails.
The gem version from rubygems.org is probably the 'best practice' now that I think about it. You can guarantee that the Rails codebase won't change out under you.
No harm in trying the github approach for a few weeks if only to learn the hard way!
Good luck
I'm adding new gems and functionality to it often. Before my last release some of my code broke in my dev environment and I found out it was because some of my gems (CarrierWave and jQuery in particular) had been updated and didn't work with some code.
What's the best way to manage gems regarding versioning? Some seem to say that you should always specify the version number in your Gemfile...but for all gems? Just some?
I know that for some gems you may have to store the version numbers because of bugs, etc. But these aside, in development there are times where I'm adding new gems and may need to do a bundle update to get the new stuff working but then don't want to break old stuff.
I have good tests to hopefully catch a lot of errors before pushing to production. How are other users ensuring gem update may not break completely unrelated functionality when in development?
Unfortunately, if you dont' want you app to break because of backward-incompatible gem updates, you do have to specify gem versions. What I found to be a good practice is using the pessimistic operator ~> to specify gem versions. For example:
gem carrierwave, '~>0.6.0'
This means the carrierwave gem will be frozen at version 0.6, but bundle will install any minor, backward-compatible updates and bug fixes, which are usually increments of the last number (0.6.1, 0.6.2...). That means you can update your bundle without running the risk of breaking something (no more flinching when running bundle update).
You can also use the pessimistic operator on major versions:
gem devise, '~>2.0'
Meaning bundle will update to versions 2.1.0, 2.2.0, 2.2.1, 2.3.0, but never to 3.x.
Some considerations:
You don't have to specify all gem versions, but it's good practice. I don't specify versions of my own gems, for example. But every third party gem has its version specified. Otherwise, I'd be trusting my code to things beyond my control.
You still need to have a certain amount of trust in the gem maintainers to use the pessimistic operator. A reckless maintainer still could release backwards-incompatible changes in a minor version. In those cases, I lock the minor version (no pessimistic operator).
If you specify gem versions, you'll be making bundle's work of resolving gem dependencies a lot easier, meaning it'll do it much faster.
As a Rails developer I feel a bit stupid asking this question but hopefully I will learn something new and someone can put me out of my misery! In my rails applications I use (other peoples) gems all the time, I also use plugins from the community or my own.
I understand the benefits of use gems over plugins as they are version-able, segmented, system wide, easier to manage and share etc etc but I don't really know how to go about making a gem for my rails apps!?
Do you always start with a plugin and convert it to a gem, I've seen the words 'package it as Gem'. Also the gem I'm thinking of building would be no good in a normal ruby program, it's only useful to rails apps. I'm not even sure if the semantics of that make sense, 'RubyGem' that will only work in a rails application!?
I would like to create a gem (if that's what I should use?) for a discrete piece of functionality for my rails apps. It will need to add a database migration, new routes and provide controllers and views or useful view helpers. I'm know I can achieve this via a plug-in but would just like to know how/why to do it as a 'Ruby Gem'?
To avoid the risk of Over-engineering, I usually start with the feature I need directly into the application. Then, as soon as I need to use the same feature into another project, I check whether it is worth to extract it into a plugin or even a separate application providing an API.
Plugins and Gems are often interchangeable. Gems provides several significant advantages in terms of reusability and maintainability.
On the other side, there are some specific known issue. For instance, a Rails app actually can't load rake tasks defined into a plugin packaged as a Gem.
Almost every Rails plugin can be packaged as a Gem.
For instance, take my tabs_on_rails plugin.
You can install it as a Gem specifying the dependency on environment.rb. Or you can use script/plugin install command as you would expect.
If you want to achieve the same result, make sure to follow the standard Gem layout and provide the init.rb initialization script required by Rails.
Also, you might want to create an install.rb and uninstall.rb file to include the post-install and post-uninstall hooks when the plugin is installed as a standard Rails plugin.
Last but not least, if you package a plugin as Gem you can reuse it in non-Rails projects and provide Rails-specific initializations using the init.rb file. Non-Rails applications will simply ignore it.
If you want to make a plugin for Rails, https://peepcode.com/products/rails-2-plugin-patterns gives you a good start. After that, make the plugin into a gem.
To make a gem, this resource http://railscasts.com/episodes/183-gemcutter-jeweler will be helpful.
As of 2013 you'll want to use Bundler and the following tutorials:
#245 New Gem with Bundler -
RailsCasts
Make your own gem - RubyGems
Guides
Take a look at Jeweler. Jeweler gives you a set of rake tasks to make gem versioning and building very easy.