nested rails gems and gem management - ruby

Rails is collection of several gems, all who's source resides in the rails repository, aka active_record has its own gemspec but is at github.com/rails/rails/active_record. While I use this stuff all the time, I dont really know the details of creating my own gems using this strategy. I have a project for work where certain codebases will be reused from project to project, and think that I would like to build gems for each recurring toolset. While the gems will always be used in a namespace, eg Company::LegacyRecord I think it would be ideal to have LegacyRecord, in this case be its own gem. What would be the rationale for building a collection of gems with a toplevel namespace, like Company, in my example, or rails as the top level namespace, versus gems that are totally independent?

you probably only need to do that for very large projects. The benefit is that you can "split up the functionality" across gems and each one is more specialized.

Related

Why the Ruby Gems code have certain file that just requires file with same name but the only difference is they have snakecase?

For our current question, let take this repo as an example.
https://github.com/slack-ruby/slack-ruby-client/tree/master/lib
In this repo, we can see the following list of files.
The slack_ruby_client.rb just has require 'slack-ruby-client' in the file. I am seeing similar convention in few other gems as well. Another example is https://github.com/orbit-love/notion-ruby-client/tree/main/lib
Is there something with the logic in here? Can someone please explain me or direct me to any article that talks about this?
Because a lot of programmers don't understand that slack_ruby_client and slack-ruby-client are not the same thing, and so the authors of the gem provide both files to avoid being flooded with bug reports.
The authors of Nokogiri did the same thing because programmers kept mis-spelling it as require 'nokogirl' instead of require 'nokogiri' and reporting bugs that it is not working, so the Nokogiri authors just put in a file named nokogirl.rb which just contains require 'nokogiri'.
At first, the default entry point of a gem is commonly the exact same file as the name of the gem, as this follows the hardcoded defaults of bundler. There is also a potential conflict of conventions used in naming gems, ruby files and the mapping to constants (classes, modules, ...) in those files.
At first, when adding a gem as a dependency to your Gemfile, bundler may try to automatically require the gem. Here, it uses the name of the gem dependency by default (this can be overridden with the :require option).
Because of this, the normal entry point for the slack-ruby-client and notion-ruby-client gems is named the same as the gem. Bundler is thus able to require the gem code without any further instructions.
Now, there are other ways to require Ruby code than to just rely on bundler autorequiring. Often, developers manually require code to ensure that their dependencies are guaranteed to be loaded, regardless of whether bundler is used or not.
The usual convention when naming ruby code files is to use snake_case names named after the respective class / module defined in the file. A class names MySpecialClass would be defined in a file named my_special_class.rb
Given that the gem is called slack-ruby-client and people being aware of this specific name, they might thus assume that they can or should require the gem as require "slack_ruby_client", assuming that snake_case file names are used here (as would be true most of the case in Ruby). The slack-ruby-client gem supports this assumption by providing an appropriately named file which loads the actual module.
Additionally, when manually requiring code, many people assume that they can just require the desired module using its module name converted to snake_case. In the case of the slack-ruby-client which provides a Slack module, people may thus assume that they can just use require "slack" to load the module.
Accordingly, the gem also provides a file called slack.rb which requires the actual entry point for the gem.
In the end, those files are added by gem authors to provide convenience entry points for people assuming various conventions for naming gems and / or files in them in order to provide the correct functionality seamlessly.

Ruby beginner - using /modifying existing gems in single project

As the title states, I'm a beginner in Ruby.
My project uses 2 existing gems - which I want to modify.
I've forked the gems on GitHub and put them as modules in my repo and they show up as a subdirectory.
I've tried researching this, but I keep on getting lost - I'm thinking I'm missing some basic concepts/knowledge here.
My questions:
Am I going about this right/wrong?
Is it even possible to include the code of those (forked) gems in my actual project, or should I update them separately and just use them as actual gems with require (this seems very cumbersome)
If these gems are part of my project, how do I use them properly, I assume I don't need the require piece? If not, how do I access/use them?
Thanks!
BTW, using Ruby 1.9.2-p194 on Ubuntu with RubyMine as the IDE.
Probably wrong. Ruby is a very flexible language, and has what are called open classes. This means that you can open up and change classes at run-time. Doing this on an external library is called monkey patching. So instead of having to replicate all of the code you want to stay consistent, you can just modify the classes and override any methods you want.
A simple example:
class Fixnum
def is_multiple_of_three?
self % 3 == 0
end
end
However, if the changes you want are really significant, it could make sense to fork the gem.
I recommend the bundler gem. This will let you make a Gemfile which lists all of your dependencies. You can list a github repository as a source for the gem, like so:
gem 'gem_name_here', :git => 'git://github.com/username_here/gem_name_here.git'
and then run bundle install to install your dependencies.
If you install the gems with bundler, it acts just like any other gem you have installed.

Customize Gems or merge into main rails project

Currently I am writing a Ruby on Rails application, and I am using Gems, however sometimes I feel that Gems are not as flexible as I want them to be. To make them more flexible. Should I
Fork them on github, and customize it, but this still present the challenging of managing everything.
or
Strip and merge the code of the gem to the main application? This will allow further customization of the gem. This would be for situations where a Gem require another Gem's functionality.
or is there a better way of doing this?
Thanks
B
Choice A is the better answer for a number of reasons.
You get to merge in security updates, enhancements, and bug fixes easily.
Your changes may get merged into the core--in fact, consider if you could implement them in such a way as they live alongside the core functionality as options. If this happens, you have the ultimate win--nothing to maintain, and you can retire your fork.
Others can benefit from your changes.
Your project's footprint is kept smaller and focused by keeping the gem code isolated.
You'll have something to add to your Github "resume."
If its some kind if not so popular gem or "bicycle" from some previous studio or developer who started project(in my case).
I prefer deprecate this gem's and move code into project,
for example they have c***la-deploy - it's just wrapper to Capistrano 2 with own methods))) - I just delete it and rewrite on last Capistrano 3
Than that have own "CMS" c***la-cms where they wrap standard form_for or simple_form with name "twitter_form_for" ? - fist of all I start try to find gem who use this name, and than find in dependency gem's ...
Its take a lot of time for new developer involve in project - better move to standard rails methods/heplers
But anyway i understand for a what this studio do that - its just vendor lock and for client more hard to move out from them to another developers.
For example for startup its bad to use a lot of dependencies and if it's just simple website - dose not matter.

What's the best practices in code reuse between different Ruby projects?

guys!
I'm a software developer with Java background and I'm starting some projects using a Ruby web framework (Padrino/Sinatra).
In my java projects, I usually had some "common" projects whose classes where used in several projects. For instance, I had a central authentication service, and a shared database that stored the user profiles. All my projects that used this service shared some models mapped to the user profile database.
So, despite the framework, orm lib etc., what's the best way of sharing code across several Ruby projects?
Besides this, ruby's gems is one of the best way of reusing common parts of code. Gems have names, version numbers, and descriptions and therefore you can easily maintain up-to-date versions of these libraries, install and uninstall, manage your computer’s local installations of gems using the gem command, available from the command line. Gems became standard with Ruby 1.9, but before you have to use require 'rubygems' line in the scripts. There are several tools that help create them, for example, bundler. Bundler not only tool for gem creation, but an awesome application's dependencies manager.
Put your code into a something.rb file and require it at the top of your other script(s).
You can also use load instead of require, but require has the nice property that it will not include a file more than once. Also, using load requires the .rb extension, whereas require does not, i.e.,
#some_script.rb
puts('hello world')
#another script
require 'some_script'
>> hello world
load 'some_script'
LoadError: no such file to load -- some_script
from (irb):2:in 'load'
from (irb):2
You will almost always use require, but load is an option as well if you want to use it for... whatever reason.

Referencing multiple local ruby gems in development using Bundler

I currently work on an application that consists of many gems. Each of these gems are being developed at the same time, and it is important for us to reference our current local copy from each of the gems.
We currently use Bundler in each of these gems. Currently we are setting an environment variable that tells Bundler to reference our local copies as opposed to the system installed gem.
While this works, it is messy because:
1) The Gemfile.lock is constantly changing when we flip back and forth. This results in errors when deploying.
2) This relies on all developers keeping their directory structures exactly same, unless we also make this configurable (sucky).
What do other people do in this situation?
Upload your gems to private repositores in github, for example, and let Bundler feed from them. Your gem developers should have their repos updated.

Resources