How to release a gem that depends on unrelated code? - ruby

Didn't really know how to title this. First time writing a gem so not sure about the best way to do it.
I am releasing a "Graphics" Ruby gem that uses a 2D Array class that I wrote. Which of the following 2 approaches is best?
Put the 2D Array class in the gem. This is fine, but I will be updating the class and I don't want to have a complicated process of updating it in one place and then copying the files into the gem and updating it.
Release the 2D Array class as a separate gem, and have the Graphics gem depend on it. I guess bundler handles this dependency so it is easy for people to use...?
Are there any other reasons to choose one over the other? Which is the best practice?

Actually, your users don't need bundler: rubygems itself handles the dependencies of gems, and yes it will be easy for people to use.
The choice between 1 and 2 is up to you. There will be some extra overhead involved to document and maintain two separate gems. If you know for sure that the 2D array class is useful on its own and you have other places where you want to use it, making two gems is a decent idea.

Related

Ruby's `.present?` without Rails?

I'm developing a "Rails-less" Ruby daemon for automation (although in theory it runs within a Rails directory). For general purposes and the principle of the matter, I would like to find the (most) "native"/common way to utilize a Ruby version of .present?/.blank?/.empty?/.nil? to identify if an array or a (hash) value exists and is not empty (i.e., [] or {}).
From what I've read (e.g., Stack Overflow) and tested, all of these functions appear to be Rails-specific methods, part of ActiveSupport(?).
Coming from other web/interpreter languages (PHP, Python, JS, etc.), this is a general logic function most languages (with arrays, which are most) have this functionality built in one way or another (e.g., PHP's isset( ... ) or JavaScript's .length).
I understand there are RegEx workarounds for .blank?, but .present? seems it would require exception handling to identify if it's "present"). I'm having a hard time believing it doesn't exist, but there's little talk about Ruby without Rails' involvement.
Active Support is broken in small pieces so that you can load just what you need. For .blank? and .present? methods it would be enough to require:
require 'active_support/core_ext/object/blank.rb'
As docs say.
Object#nil? , Array#empty? and Hash#empty? already defined so you dont need anything to require to use those.
Make sure active_support gem installed in your system
You can use ActiveSupport without including all rails in your app, that's actually quite common.
nil? and empty? are defined in the standard library.
E.g., String#empty? is simply testing if the length is 0.
To use active support, just install the gem or add it to your gemfile then:
require 'active_support'
The documentation also states you can cherry pick the core extensions you want:
require 'active_support/core_ext/object/blank'

ruby module structure insight

I'm new to Ruby and i'm making a Ruby package.
structure is:
eventsims (main folder)
|__lib
|__eventsims {subfolder)
| |__discrete.rb
| |__randgen.rb
| |__simevent.rb
| |version.rb
|__eventsims.rb
If i put all the codes in my three modules file (discrete, randgen and simevent) in the ["Eventsims" module inside the eventsims.rb file], it is easy but there would be up to 1000 lines of code which I don't want
Now I have a "require" lines of code inside eventsim.rb that requires all these four files in the eventsim subfolder.
I can use all the modules, no errors.
for example in the discrete.rb, a module called Discrete with a Calculate class having an expectval method:
Is this how I would be able to use the package after installing it with Rubygems
require "Eventsims"
a = Discrete::Calculate.new([1,0,4,2], [0.2, 0.4, 0.6, 1.0])
a.expectval()
and if yes, is it sensible to have it that way because so many modules I've seen will have something like:
require "eventsims"
Eventsims::someclass.new
which in my case would be
require "eventsims"
Discrete::someclass.new
I'm worried about the consistency of the required file and its namespacing. require eventsim and its different Discrete
Sorry the question is really long.
Unlike some other languages, Ruby does not tie the filesystem names to module hierarchy. If you want to have require "eventsims" provide the module Discrete, you can. Whether or not it's a good idea, it is for you to decide - Ruby is not your Mum. There are two potential pitfalls:
Gem users might get confused, and wonder how to use your gem
Someone in some other gem also defines Discrete and you have a collision.
A compromise between the two approaches (having a distinct namespace and having less to type) is to indeed have a top module EventSims, and for users to include it if they want to access the next level down directly:
# safe usage
require 'eventsims'
EventSims::Discrete::Calculate.new
# easy usage
require 'eventsims'
include EventSims
Discrete::Calculate.new
# restricted easy usage
require 'eventsims'
module MyCode
include EventSims
Discrete::Calculate.new
end
EventSims::Discrete::Calculate.new
This way, you still have namespacing, and you can get rid of it when you know there is no collision in your code. Going the other way around (having no namespacing and trying to isolate the code when a collision does happen) is significantly more difficult.

How to have multiple gems that share the same common Ruby module?

I've written a Ruby module, common_services.rb, which contains convenience methods for interfacing with a web service; I consider it a piece of common code. Now, I would like to create two separate gems, both of which utilize the convenience methods in this module. I visualize something like this:
rubyStuff/
commonCode/
common_services.rb <-- common code lives here
gemA/
bin/
lib/ <-- gemA would like to pull in common_services to use it
gemA.gemspec
gemB/
bin/
lib/ <-- gemB would also like to pull in common_services to use it
gemB.gemspec
Each of gemA and gemB would have a reference to the common code in order to use it, for example rubyStuff/gemA/lib/gemA/main.rb might begin as:
require_relative '../../commonCode/common_services.rb'
puts CommonServices.getMessageOfTheDay()
<etc>
It's not working out too well for me, so I'm wondering if there is a better way to do this in Ruby. One problem I'm having is with packaging a gem to reference a file that is outside of its own path:
s.files = Dir['bin/**'] + Dir['lib/**/*'] + Dir['../commonCode/**']
When using the .. notation in the gemspec, and trying to install the resulting gem, produces:
ERROR: While executing gem ... (Gem::Package::PathError) installing into parent path /Users/me/.rvm/gems/ruby-2.0.0-p247/gems/commonCode/common_services.rb of /Users/me/.rvm/gems/ruby-2.0.0-p247/gems/gemA-0.0.1 is not allowed
It makes sense to me why gems are not allowed to reach outside of their own path, but I'm not sure how to resolve this issue. In Ruby, how and where should I organize Ruby code that will be used by multiple gems in my codeline, so that the multiple gems can use this common code? Am I going about reuse entirely the wrong way? Symbolic link magic?
Thanks for taking the time to read through this.
Summarizing comments above for posterity...
There are a couple things to consider here.
1. Is commonCode significant? Is it a good chunk of code, or just a few files?
2. Are gemA and gemB significant? Should each of them really be gems?
Seems like you're in either one of two situations, depending on the significance of the code you've written:
commonCode is significant enough (amount of code, complexity, logical separation from gemA and gemB) to merit its own gem? If so, definitely pull it out into its own gem. You can require gem-common in the other two. It doesn't make sense to require a plain ruby file in A and B that lives outside of those two code bases.
commonCode is too insignificant to be pulled into its own gem. If this is the case, you should consider whether or not gemA and gemB really deserve their own gems, each. If they aren't big enough or logically separate enough, maybe all three can be combined into a larger gem.

Advice on how/where to place requires in own gem

I am going through the blog Creating mountable Gem:
Its important to note that you should require your dependent gems explicitly in the root file of your gem. Say if your gem is named my_cool_gem, then you should have my_cool_gem.rb created inside lib folder. If your gem is dependent on strong_parameters, then you need to add these lines:
The author did not mention why it is required to have the dependent gems explicitly in the root file. Can some one explain why this needs to be done?
It's just cleaner. What if you had require statements in various files scattered all over your gem? It'd be a mess to easily see all the dependencies.
This statement:
Its important to note that you should require your dependent gems
explicitly in the root file of your gem.
It is not a strict statement that you have to conform to (to be fair to the author, the word is "should", not "must"). Some people prefer to take a different approach, and e.g. require dependencies only in parts of the library that use them.
However, you do need to consider:
Execution order of require statements that define symbols used elsewhere. You cannot call a DSL method that sets up instance methods for you, if the gem that provides the method has not yet been require-d
You should check that you really do require all correct the dependencies, and your gem functions correctly in projects that do not load them already.
With both of these in mind, it is often quickest and easiest to require dependencies early and and in a way that can be quickly viewed. So the advice is sound; as it was presented in a very short article, covering the statement with caveats and extra background would make the whole thing a lot less pithy.

Do ruby gems ever conflict?

As a ruby newbie, I was wondering, will gems ever conflict with eachother? For example, if 2 gems overrode the << method on array, which would win, or is there something to stop this?
Thanks
I assume you are talking about redefining methods, not overriding them, right? If two libraries overrode the same method in two different subclasses, there wouldn't be any problem.
If two or more libraries redefine the same method, then whichever one happens to be loaded last wins. In fact, this is actually no different than just one library redefining a method: the Ruby interpreter provides an implementation of Array#<< for you, and if you redefine it, your definition wins, simply because it came later.
The best way to stop this is simple: don't run around screwing with existing methods. And don't use libraries that do. The -w commandline flag to enable warnings is very helpful there, since at least in Ruby 1.9.2 it prints a warning if methods get redefined.
In Ruby 2.0, there will probably be some kind of mechanism to isolate method (re-)definitions into some kind of namespace. I wouldn't hold my breath, though: these so-called selector namespaces have been talked about in the Ruby community for almost 10 years now, and in the Smalltalk community even longer than that, and AFAIK nobody has ever produced a working implementation or even a working design for Ruby. A newer idea is the idea of Classboxes.
As far as I can tell, you're talking about monkeypatching (also known as duck punching in the ruby community).
This article has another example of monkeypatching (and other practices) gone bad.
In practice, no, though you could probably construct a situation like that if you really tried. Here's an interesting article (though old) that explains how this could happen.
If two gems "overrode the << method on array" they would need to be subclassing Array, and those classes would have different names or be in different modules.

Resources