How should I store the version number of my code inside a ruby gem?
I've seen two techniques in the wild:
<gem root>/VERSION which only contains your semver.
<gem root>/lib/your_gem/version.rb which contains the following code:
module IfYourCodeIsInAModule
class YourGem
VERSION="0.0.1"
end
end
I like 1. because it's really obvious. I like 2. because it's part of my code, I can write to logs with my version number easily.
I don't like 1. because if I want to access the version number from within my code I have to do a file read (not the worst thing ever), I don't like 2. because if my core class extends from another class then I have to have that decendency in the version.rb too (or else get a superclass mismatch) - eg.
module IfYourCodeIsInAModule
class YourGem < OtherWork
VERSION = "0.0.1"
end
end
When you require this file from your actual code for runtime it's all good. When you include it in your gemspec you suddenly need to require 'other_work' to get your Version number!
I'm happy to go and roll my own solution, but this can't be a new problem, what's the community doing, and what's the general wisdom on this?
I am no expert on gem VERSION ethnology, but perhaps this non-expertise makes me all the more average and better suited to answer the questions on "general wisdom".
So, general wisdom is, use Bundler. And once you create your gem by bundle gem my_gem_name, you will see that the bundler automatically creates lib/my_gem_name/version.rb file and requires it from your lib/my_gem_name.rb. So I would suggest that if you decide not to use bundler and roll your own gem on your own, you still should keep a separate version.rb file containing only
module MyGemName
VERSION = "0.0.1"
end
That is, straight under the main module. You then load the version.rb from lib/my_gem_name.rb. Of course, if your code is organized in a more alien way, then you need to improvize more.
Related
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.
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.
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.
I am creating a graphics library gem.
When creating a gem it seems that it is important to make sure that there are no conflicts with other gems or other code.
For example, extension (monkeypatch) methods are called from within my gem code.
class Array
def sum
inject(0.0) { |result, el| result + el }
end
So, the solution seems to be a module.
How to create a module and ensure that there are no conflicts with other code when the gem is downloaded and used by others?
You just do it. Create a module, and use it:
module MyLibrary
class MyGraphicsClass
# ...
end
end
This in no way helps prevent your monkey patches from stomping on other people's toes. There is no way to prevent your modification to Array from potentially breaking other people's code. The solution is to not do that. Patching fundamental parts of the standard library is a horrible practice, and a great way to make sure nobody wants to touch your gem.
I'm reading through "Programming Ruby 1.9". On page 208 (in a "Where to Put Tests" section), the book has the code organized as
roman
lib/
roman.rb
other files...
test/
test_roman.rb
other_tests...
other stuff
and asks how we get our test_roman.rb file to know about the roman.rb file.
It says that one option that doesn't work is to build the path into require statements in the test code:
# in test_roman.rb
require 'test/unit'
require '../lib/roman'
Instead, it says a better solution is for all other components of the application to assume that the top-level directory of the application is in Ruby's load path, so that the test code would have
# in test_roman.rb
require 'test/unit'
require '/lib/roman'
and we'd run the tests by calling ruby -I path/to/app path/to/app/test/test_roman.rb.
My question is: is this realy the best way? It seems like
If we simply replaced require '../lib/roman' in the first option with require_relative '../lib/roman', everything would work fine.
The assumption in the second option (that all components have the top-level directory in Ruby's load path) only works because we pass the -I path/to/app argument, which seems a little messy.
Am I correct that replacing require with require_relative fixes all the problems? Is there any reason to prefer the second option anyways?
Further on, that same book makes use of require_relative (Chapter 16, Organizing your source code) in the context of testing, so yes, I would say that using it is a Good Thing, since it "always loads files from a path relative to the directory of the file that invokes it".
Of course, like #christiangeek noticed, require_relative is new in the 1.9 series, but there's a gem that provides you with the same functionality.
It might be worth pointing out that the Pickaxe too provides a little method you can stick in your code in the same chapter I mentioned before.
require_relative does make the code cleaner but is only available natively on Ruby > 1.9.2. Which means if you want want your code to be portable to versions of Ruby < 1.9.2 you need to use a extension or the regular require AFAIK. The book is most likely a) written before 1.9.2 became widespread or b) providing a example for lowest common denominator.