My team and I are constantly updating our Gemfile and these 2 lines which are on line 60 and 61 in our app are constantly changing. We want them to stay the same. Is there any way we can make it so that these lines never change? but to still be able to check stuff into our Gemfile?
group :development do
gem 'ph_app', path: '/Users/joe12/Desktop/VBR/ph_app'
end
Another answer involving a separate file:
Use the contents of another file using eval. In your Gemfile, add these lines:
other_path = __dir__ + '/Gemfile.local'
eval File.read(other_path) if File.exists? other_path
A developer may create a Gemfile.local and add their custom gems there like so:
group :development do
gem 'ph_app', path: '/Users/joe12/Desktop/VBR/ph_app'
end
This version is not very intrusive (but for the extra lines in the Gemfile). It is very flexible since the local configuration is optional. No need to supply an empty file on production machines. This is a good solution if the gem 'ph_app' is optional in the development environment.
This solution is a bit similar to using a different Gemfile (see other answer) but configured with --local. But more flexible :)
Note that the entries for custom gems in Gemfile.lock will differ on a per developer basis. Developers will need to be careful when adding their changes to version control.
As requested, an answer involving an environment variable:
Use this in your Gemfile:
group :development do
gem 'ph_app', path: ENV['PH_APP_HOME']
end
And have every developer set up that environment variable in their environments. On a Linux or OSX that would typically go into ~/.bash_profile, e.g.:
export PH_APP_HOME='/Users/joe12/Desktop/VBR/ph_app'
If you run rails specific binaries from within your IDE, then you will probably have to set up the environment variable there, too.
This will not interfer on production and test environments since the :development group will not get bundled there. (You did set up those environments accordingly, right?)
Note that the respective entry in Gemfile.lock will differ on a per developer basis. Developers will need to be careful when adding their changes to version control.
As requested, an answer involving a separate file:
Use a non-default Gemfile as a developer. This is the least intrusive solution for the project but probably also the least convenient for the developers.
Create a Gemfile.custom alongside the Gemfile, containing developer specific gems:
eval File.read(__dir__ + '/Gemfile')
group :development do
gem 'ph_app', path: ENV['PH_APP_HOME']
end
The Gemfile.custom should be ignored by version control.
The eval is an ordinary Ruby instruction. Together with File.read it will cause the other file to be read and its contents be interpreted. You can use the bundler DSL in that other file without doing anything special.
Execute this from the project root to start using the alternate Gemfile:
bundle config --global gemfile Gemfile.custom
Using --global will set the value for all projects on the developer's machine (for that user). And here is why developers might not like this solution very much: Every bundled project on their machines will need a Gemfile.custom.
Alternatively, the custom Gemfile option can be supplied to a bundler command. That way, other projects will not be affected, but every bundler command will have to be amended with the option. Binstubs might make this more convenient, but I did not try that.
Note that the entries for custom gems in Gemfile.custom.lock will differ on a per developer basis. Developers will need to be careful when adding their changes to version control.
You need to use "git filters" and a combination of 'clean' and 'smudge'. The post here explains in greater detail:
How to tell git to ignore individual lines, i.e. gitignore for specific lines of code
An answer involving relative paths:
Do not let your developers decide where they want to put that other project ph_app but instead make them put it in the same directory as the host project. (Not nested but in the same parent directory.)
Then add this to the Gemfile:
group :development do
gem 'ph_app', version: '2.1.32', path: '../ph_app'
end
Note the added version string. Thanks to that, bundler will make sure that the local files actually provide the requested version of ph_app. Every developer will need to manually pull the most recent changes from version control. And they might also have to manually switch branches there as the host project switches branches. Maybe this could be alleviated by means of git triggers.
If needed in your production environment, you can supply ph_app in the same manner, there too. Then you will need to install the correct version of the gem with your deployment script. However, referring to your version control server (e.g. github) will be easier and also ensure that the two projects stay in sync.
The entry for the ph_app gem in the host project's Gemfile.lock will be the same for all developers. It will only include the version string, i.e. no commit hash. Nice and easy :)
Related
We are looking into building a very large rails application and considering using engines for better separation of "modules" out of the main app.
we have started this process by creating a small engine using the gem motorhead (the idea of its active_if component is wanted).
That engine was then removed from the main app and given a git init, then pushed to github.
the main app then was able to pull the gem in within the Gemfile.
During this proof of concept, it works, but not very efficient, and also updating the new engine/gem is a bit awkward in this way as it is kinda a submodule in a way. What is the proper workflow for building and maintaining engines/gems when building a modular app like this?
Thanks in advance
The most akward part about deploying Gems or Engines as modules is the constant need to update. We had a lot of success with using:
bundle config local.my_gem ~/projects/my_gem/
It'll point to the Gem/Engine version on disk without modifying the Gemfile and Gemfile.lock.
To remove the local override run:
bundle config --delete local.my_gem ~/projects/my_gem/
With this you should be able to restrict the times the Gemfile.lock has to be updated to deployment time.
Recently I have noticed that trying to bundle without the "sudo" command almost always results in something like:
Could not find gem 'faye (~> 1.0.0) ruby' in the gems available on this machine.
but using sudo bundle install works like a champ.
Why would my computer be doing this?
Note
I don't really know what extra information to provide, so feel free to request anything.
With "sudo" the command is executed by the root user. When executed like this, it also includes that some environment variables are set differently, because they are needed in the context of the root user.
This might be what's happening here, that since possibly the PATH variable (or some other environment variable) is different in the sudo-environment, it can actually find the gem it is looking for. While in your normal execution environment, it can not find it, since the PATH is set differently.
Hope this helps :)
Following up on #topedro's answer: You're seeing this error because you did some actions as root, and some as another user.
Most people avoid this situation by installing Ruby and all gems as the same user who'll be executing them. E.g., your personal user account, or one set up for this purpose on a server named (usually) "deploy".
An easy way to get started from your current broken state is to install RVM as a non-root user, and go from there. You could also download the Ruby source and compile it yourself instead of using RVM.
Whatever you do, treat Ruby and the gems as simply some app owned by a non-root user, residing in that user's home directory.
Backgound
A little background to this question first: Ruby on Rails has some security issues as of late. So we need to update the Rails version on our projects. If you have a few, that gets old fast if you do it by hand... So I figured I can create a Thor task for this.
Question
This now works great! BUT! I need to respect the .rvmrc file for each project while installing the new versions of rails. I want this script to be OpenSourced soon, but I want to tacle the problem of not respecting the .rvmrc file first.
So what I need is a way of using the right RVM ruby version/gemset when I change to a directory to update the Rails version.
How is the way for this to be done? Can it be done from the Ruby script in a way so that it works on Mac and Linux, regardless of Shell (found a answer with zsh support, but what about all the other shells out there?)
Quick Example code:
#Scan the base directory down for Gemfiles
gem_files = File.join("**", "Gemfile")
Dir.glob(gem_files){|gemfile|
project_folder = File.dirname(gemfile)
puts "Found Gemfile in #{project_folder}"
Dir.chdir(project_folder) do
#TODO: Respect/load the rvmrc file in this directory
update_gem_file(project_folder) #example
run 'bundle update rails' #<--- needs to be done in the RVM gemset
end
}
Just to give you an idea of what I'm trying to do.
Link to the script on the githubs
The github repo for my script -- Work in Progress!
Check out this project https://github.com/versapay/bundler-auto-update it basically:
Attempt to update every single gem of your Gemfile to its latest patch, minor then major release. Runs a test command to ensure the update succeeded
As for RVM use this simple code:
#Scan the base directory down for Gemfiles
gem_files = File.join("**", "Gemfile")
Dir.glob(gem_files){|gemfile|
project_folder = File.dirname(gemfile)
puts "Found Gemfile in #{project_folder}"
run "rvm in #{project_folder} do bundle-auto-update -c rake spec"
}
You can find more details on scripting with RVM on https://rvm.io
Blindly upgrading Rails is not a good idea. At least run your test suite to ensure nothing breaks. After that you still want to do some QA on the app to make sure you didn't break all the things.
Then, How do you know that the current branch you're updating is actually the main develop branch? Don't you want to create a 'hotfix' branch and apply it to your production and development branches?
But, let's say you did manage to upgrade all your apps, they are still not deployed to production.
Isn't the point of the project .bundle/config to specify config that is relevant to the project?
On the bundle-config manpage is says:
This command allows you to interact with bundler's configuration
system. Bundler retrieves its configuration from the local application
(app/.bundle/config), environment variables, and the user's home
directory (~/.bundle/config), in that order of priority.
So ensure that you don't have any configuration files that are taking priority over the one you want to use.
You can configure this file yourself or set options using bundle config (option), running bundle config without any options prints the current configuration.
For example you can set compile time options for they mysql gem like so:
bundle config build.mysql --with-mysql-config=/usr/local/mysql/bin/mysql_config
So yes, app/.bundle/config is used to set bundle options for the current project.
Edit:
This change was added in commit efa85055 to the Rails github repo. You can view that version of the file here and the commit here.
The commit message is from José Valim and mentions the line you have a question about:
Make bin/rails call rails/commands/application, fix generators usage
and update .gitignores.
Edit Again:
This is a quote from bundler on why you should not check the .bundle directory into any VCS.
Do not check in the .bundle directory, or any of the files inside it.
Those files are specific to each particular machine, and are used to
persist installation options between runs of the bundle install
command.
Trying to understand this open source app on github, it has a gem file:
https://github.com/bestbuyremix/BBYIDX/blob/3f8d378ef318544411aa887c4ef71e1ab8a9efd0/.gems
And a plugins folder:
https://github.com/bestbuyremix/BBYIDX/tree/3f8d378ef318544411aa887c4ef71e1ab8a9efd0/vendor/plugins
Why would you want to do this? Does this make upgrading the plugins harder?
When you reference a gem, from what I understand, it downloads the files and stores them at a global level (gemset if using rvm etc), so I guess loading it as a plugin gives you access to the source to modify?
i.e Why go with gem versus a plugin or visa versa?
Plugins give you the flexibility of being able to just copy your app somewhere else and poof! it's all ready to go.
Gems on the other hand, force you to a) download them to every single piece of hardware that your app is running on via rake gems:install and b) force you to keep track of which packages are installed on which system.
With plugins, you know that when you stick it in your vendor directory, it will work immediately.