Is it possible to automatically identify Ruby gems that are no longer in use within a Rails project?
For example if a fellow developer added gem 'nokogiri' to the Gemfile, for a piece of functionally, but the code that depended on that gem has now been removed. I am looking to port my entire project to jRuby so removing the gems that we no longer seems a very sensible starting point.
Thanks
Usually gems are used in a specific way, so for each one you will have to look for patterns manually.
For example, if I had to figure if Nokogiri is being used, I'd use git grep to find Nokogiri occurrences (I assume you use git):
git grep Nokogiri
If nothing is returned, you are probably not using it.
Another way is, if you have a test suite, is just to remove it and see if something breaks. Not foolproof, but if you have good tests it should be a pretty safe path.
On rubyforge there is a gem called gem_unused. It adds an 'unused' command to 'gem'. However, I am not able to test this as it seems to be failing on my system. (I'm new to the rails world so maybe this is an issue someone else could troubleshoot. I filed an issue on it on the maintainer's github)
Related
I've got some helper code (monkey patches) I tend to carry around from rails project to rails project via simply copying files or pasting code into the initializers folder.
I think a clean way to deploy different categories of my initalizer code would be to simply add gems to my project Gemfile that would do the equivalent of this for me. I'm not very skilled at creating gems or the deeper side of ruby on rails engineering so I just wanted to know if this were possible before I got started with it.
Yes, this is definitely possible. It should be probably enough to make a simple gem, put your monkey-patches there and require them in the gem entry point (e.g., if the gem is called foobar, then bundler will require lib/foobar.rb by default).
There is a guide on creating gems available in Bundler docs. In case you need to interact with Rails application configuration, you can take a look at Rails Engines.
I'm building a social network and have been using the gem community_engine but have been having trouble implementing the large amount of customization that I need for my app. I figure this will make it easier for me to override and add methods, as well as help me to better understand and learn from the code since I will be able to actually see all of it in action.
So far in my attempt I downloaded the source code, added the default bin directory and config files that were missing, as well ass all the gem dependencies.
What else do I need to do to get the app to work? I realize that there may still be a lot and that it might not be easy to explain, but at the very least is there any sort of documentation out there that might help me understand how to convert the gem to a Rails application?
Heres the community_engine repo: https://github.com/bborn/communityengine
Because this idea may draw some criticism, I'll add that I was originally building the app without any huge plugins accept for devise however I'm running out of time to finish this.
More stuff I've tried:
Moving files to a new rails app, got server to run but encountered many seemingly random errors, fixed a few but more just seem to pop up that I cant figure out:
I also took a look at http://guides.rubyonrails.org/plugins.html but this gem seems to go beyond that.
I would suggest that you clone the gem and begin copying files from the gem into your a new Rails application.
The engine gem probably has a similar structure to a Rails application, so you should be able to move the files from the corresponding folder to the same folder in your Rails root folder.
You may need to move gem files out of modules, change namespaces etc. Relevant folders to look at files you'll want to include might include app/ config/ db/, any gem dependencies in Gemfile or the gemspec file, as well as spec/ or test/.
Beyond that I think there's no silver bullet answer to your question, you're just going to have to work through problems until you have this up and running, and perhaps ask subsequent questions if you hit on an obstacle that you don't get beyond.
I think what you're looking for is a way to hook your Rails Engine into a rails app. The Hooking Into an Application section of the Getting Started with Rails Engines guide should be exactly what you're looking for.
Here are two additional resources on Rails Engines.
A Guide to Rails Engines in the Wild
Rails::Engine - Ruby on Rails API
If you are developing the ruby on rails main code base is highly useful to replace the various gems in /usr/lib/ruby/gems/1.8/gems/ with symlinks.
For example, if I have cloned ruby on rails 3.2.0 to /home/me/rails, then to create a symlink at /usr/lib/ruby/gems/1.8/gems/railties-3.2.0 that points to /home/me/rails/railties, and to do this for every needed gem.
This is useful because if you create some feature that you need, then you can try it out right away instead of reinstalling all of the gems. I've created a script that automates this, but I would imagine that there is a better way to accomplish this 'the rails way'.
You can always use the :path option in your Gemfile to specify the absolute path to any version of Rails you want. This makes your overrides more explicit.
On my server (or laptop for that matter) whenever I install a gem using:
gem install mygemname
or in my gemfile:
gem 'mygemname'
It will install on the computer to some folder on my computer.
Can I go to that folder and edit the file if I want to say add some logging etc.?
If this is not possible, I remember reading that you can have the gem source code installed in your rails 3 application under the 'vendor' folder. How do I install it locally so I can edit it and add logging to it (to learn how it works etc.)
Can you?
Yes
Should you?
Absolutely Not.
Why?
Modifying the gem source makes it very difficult to upgrade to newer versions of the gem
It's much harder to debug an issue
It will cause HUGE headaches down the line
It makes it difficult to work in a collaborative environment (does every developer have the correct hacked gem?)
It causes questions like these (i.e. where should I hack a gem?)
Solutions
There are a few ways to solve this problem:
Submit a Patch
If you feel that this 'change' would benefit the entire community, find the source code (most likely on github), fork, apply the patch, write tests, and submit a pull-request. If the developer agrees that your patch is viable, it will be merged into the project and released with the next version of the gem.
Advantages
You are helping the community
You have a local copy of the gem (since you forked it) on your development machine
Disadvantages
You have to wait for the developer to accept your patch
This can be pretty time-consuming
Re-Gem
If you don't think this is something the entire community would benefit from, but you still want to allow your other developers to use the gem in a systematic way, fork the existing gem, apply your patch, rename the gem, and publish. in this case, it's good practice to prefix your custom gem with the original gem name. For example, if the gem was named foo, you would name your gem foo-my-company. You now can choose to open-source that gem (push to rubygems) or push it to a private development gem server within your organization. You still must source the original gem author in your re-gem!
Advantages
Don't have to wait for a developer
Central code base
Easily shared
Disadvantages
Difficult to update from original gem
Can be cumbersome to maintain
Local Lib (monkey-patch)
You can create a monkey-patch inside your application and override any methods or properties that don't fit your current environment.
Advantages
Quick and Easy
Easily Shared (via git - just include the patch file in your repo)
Disadvantages
Updating the gem is difficult
It's not clear to other developers that you are modifying the Gem's core
Harder to debug (is it an error with the gem or your patch?)
Fork and Source
This is my recommended option. Why did I put it last - the other ones are more common. In this method, you fork the gem from its original repository (probably on github), and then source your gem from your git repo. For example, say the gem was named foo, you would fork foo to username/foo on github. Apply you patches, changes, whatevers. Then in your Gemfile:
gem 'gem_name', :git => 'git://github.com/username/foo'
This will install and compile the gem from source at your repo every time the bundle command is run. You can also specify a particular tag and branch (recommended to stability).
Advantages
You can easily update upstream (you have a fork - pull from the upstream, merge, you have all changes)
Version control is easy (use tags and branches for various versions)
Everyone has access to the same gem source
Easy to manage updates
Disadvantages
Your "custom" code is public (although you could use a custom git server instead of github to solve this)
Conclusion
Each method has its own advantages and disadvantages (which I've tried to enumerate as best as possible). In any event, the method you suggested is not an advised method for solving that problem.
If readers have comments about other advantages/disadvantages, please list them, and I'll add them to my answer.
Sure, it's just code.
Should you? Not in general, since it could be re-installed, updated, etc.
Since you can re-open classes IMO it's safer to monkey-patch, embrace and extend, etc. This isn't always as practical as direct modification, of course.
For educational purposes (when it doesn't matter if modifications are lost), it's fine, and makes more sense than duplicating everything. AOP-ish logging is often doable w/o modifying the original source, though. Sometimes cloning a repo and using it, particularly during exploratory phases, is cleaner.
Dave Newton's advice is wisdom and you should take it, but there's nothing wrong with taking a look at it to learn something. Running gem env will show you where your gems are installed; the lib directory is where you tend to find the meat of the code.
We have had this discussion at work, and it is a practice I discourage.
Gems are made to be updated when improvements and bug-fixes are made. That will instantly wipe out the changes you have done, breaking your code.
You can freeze your version by making it read-only, or use bundler or copying the entire Ruby distribution, but in each of those you are going against the flow.
Instead, I recommend:
Write a patch to the method in question in one of your own files. I've copied the method definition into a separate file in my app's lib directory, and made the change there, then required it last, allowing the method to be fixed without subverting Gem's normal use.
Submit your change to the gem maintainer as a patch, along with your reason for needing the change.
Remove the file and the require if/when the change is accepted.
I used to work at a major corporation that decided it was a good idea to make a patch to one of the source files in their mail system. The software was not something they wrote themselves, so, as time went by, they spent more and more time having to roll in their "special" changes to the software as the vendor grew the product. Eventually, it took months to roll in the changes and made the software fragile, which is not a good thing for something that is a core-business service. Ruby's ability to redefine a method would have saved them untold dollars and months of work.
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.