JRuby, gemstash and sqlite3 - ruby

I'm trying to run gemstash with JRuby, but it seems to have a dependency with sqlite3-1.3.13 which of course fails because it requires a C native extension. I've skimmed the projects issues in github and found nothing about it not beeing compatible with JRuby 9.1.14.0. Is there a workaround to the "sqlite3 won't install in JRuby" thing?

seems that (at least on master), the sqlite3 gem should only load under C-Ruby, while under JRuby jdbc-sqlite3 is expected to be loaded/used.
https://github.com/bundler/gemstash/blob/master/gemstash.gemspec#L48
if RUBY_PLATFORM == "java"
spec.add_runtime_dependency "jdbc-sqlite3", "~> 3.8"
else
spec.add_runtime_dependency "sqlite3", "~> 1.3"
end
however this gems do not provide the same low-level API, so you need to make sure they have proper JDBC style DB operations in place while under JVM.
UPDATE: since they're using Sequel, all should work fine under JRuby ...

Related

build a ruby gem and conditionally specify dependencies

I am working on a gem that has needs to set dependencies conditionally when the gem is installed. I've done some digging around
and it looks like i'm not alone in this need.
Rubygems: How do I add platform-specific dependency?
this is a long thread
http://www.ruby-forum.com/topic/957999
The only way I can see to add dependencies to a gem is to use add_dependency method within a Gem::Specifiction block in a .gemspec file
Gem::Specification.new do |s|
# ... standard setup stuff
# conditionally set dependencies
s.add_dependency "rb-inotify", "~> 0.8.8" if RUBY_PLATFORM =~ /linux/i
s.add_dependency "rb-fsevent", "~> 0.4.3.1" if RUBY_PLATFORM =~ /darwin/i
s.add_dependency "rb-fchange", "~> 0.0.5" if RUBY_PLATFORM =~ /mswin|mingw/i
end
Based on all of the docs and threads I found on the net, I would have expected that if you install the gem on
Linux, then, rb-inotify would be a dependency and auto-installed
Mac - rb-fsevent would be installed
Windows - rb-fchange would be installed
However, it seems that is not the case. The "if" statements within the block are evaluated at the time the gem is built and packaged. Therefore,
if you build and package the gem on Linux, then, rb-inotify is added as a dependency, Mac, then, rb-fsevent, Windows - rb-fchange.
Still needing a solution, I dug around in the rubygems code and it seems the following is a broad stoke of what happens.
build all of your code for your gem: foo.gem
create a foo.gemspec file
build, package, and release the gem to a gem server such as rubygems.org
let everyone know
developers install it locally via: gem install foo
the foo.gem file is downloaded, unpacked, and installed. all dependencies are installed as well.
everything should be set and we can beging using the gem.
It seems that when the gem is built and released the foo.gemspec file is loaded and the Gem::Specification block is evaluated and converted to YAML, compressed as
metadata.gz, and included in foo.gem. The ruby code is compressed into data.tar.gz and included as well. When the gem is installed on the local developer machine,
the YAML is extracted from metadata.gz and converted back into a Gem::Specification block, however, it is not converted back to the original block.
instead, you will see something like the following:
Gem::Specification.new do |s|
if s.respond_to? :specification_version then
s.specification_version = 3
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<rb-inotify>, ["~> 0.8.8"])
else
s.add_dependency(%q<rb-inotify>, ["~> 0.8.8"])
end
else
s.add_dependency(%q<rb-inotify>, ["~> 0.8.8"])
end
end
Ok. So, I have a bird's eye view of the process, however, that does not change my desire to build a single gem and conditionally specify dependencies for a range of OS targets.
If anyone has a solution other than building multiple .gemspec files for each target OS... I'm all ears!!
I have also stumbled upon this problem in the past. The only workaround I could find was to create a Rake task for installing the dependencies. Of course, at that stage, you might just want to let the user figure out on his own which gem he is missing based on the error message he is receiving. In my case, there were several platform-dependent dependencies to be installed, so that wasn't an option.
Rakefile:
task :install do |t|
require './lib/library/installer'
Library::Installer.install
end
Installer:
module Library::Installer
require 'rubygems/dependency_installer'
def self.install
installer = Gem::DependencyInstaller.new
dependency = case RUBY_PLATFORM
when /darwin/i then ["rb-fsevent", "~> 0.4.3.1"]
when /linux/i then ["rb-inotify", "~> 0.8.8"]
when /mswin|mingw/i then ["rb-fchange", "~> 0.0.5"]
end
installer.install(*dependency)
end
Then, the user can use rake install to get install appropriate dependencies.
Conditional dependency install (not just based on platform, but based on user input, for example) is cruelly missing to RubyGems. Let's hope it'll get implemented in the future!
i have never done this myself, but there are some gems that are available in platform specific versions: http://rubygems.org/gems/libv8/versions
from what i understand it's just a naming thing, which can be configured by setting the platform option of your gemspec. have a look at the doc: http://guides.rubygems.org/specification-reference/#platform=
I have looked into this as well and have come to the conclusion that is not possible by design. Having a single 'mega gem' for all platforms causes the problem of not knowing if a platform is supported until the gem is downloaded and installed. A Gem would have to be smart enough to determine what is correct way to install depending on the platform. If a platform is not supported at all, the gem may fail horribly, opening a big can of worms. There use to be a callback after a gem was installed that was removed for the same reason, no magic to get a gem to install correctly. Some people have hacked around this using mkmf, but I suggest following the worn path of a gem per platform as the better solution.
Based on this, in a project that builds a gem for ruby and jruby, I have to manually create each gem and upload them to RubyGem. Using Jeweler this is as simple as specifing the Gemfile, but I have to rebuild the gem spec each time I package a gem. Fairly trivial when supporting only 2 platforms, but the build process is straight forward enough that it could be automated to provide support multiple platform gems.

using bundler to load different versions of gems for different platforms

So I am developing a Sinatra for both windows and linux. The problem is I'm using Thin instead of Webrick and eventmachine for windows only works with a pre-release version while linux uses the latest stable. in the gemfile you of course cannot include the same gem with different versions like so:
gem "eventmachine", "~> 1.0.0.beta.4.1", :group => :development_win
gem "eventmachine", group => :development_linux
gem "thin
I was wondering if there was a way to work around this, maybe using one gemfile for windows and one gemfile for linux, what would the command be to load one or the other.
Alternatively is there a way to perhaps in git manage just the gemfile for two different platforms, perhaps through a branch for just the file (don't know if that's possible from what I've read of git branches).
You can do it like that:
# Windows
gem "eventmachine", "~> 1.0.0.beta.4.1", :platform => [:mswin, :mingw]
# C Ruby (MRI) or Rubinius, but NOT Windows
gem "eventmachine", :platform => :ruby
Full list of available platforms:
ruby C Ruby (MRI) or Rubinius, but NOT Windows
ruby_18 ruby AND version 1.8
ruby_19 ruby AND version 1.9
ruby_20 ruby AND version 2.0
mri Same as ruby, but not Rubinius
mri_18 mri AND version 1.8
mri_19 mri AND version 1.9
mri_20 mri AND version 2.0
rbx Same as ruby, but only Rubinius (not MRI)
jruby JRuby
mswin Windows
mingw Windows 'mingw32' platform (aka RubyInstaller)
mingw_18 mingw AND version 1.8
mingw_19 mingw AND version 1.9
mingw_20 mingw AND version 2.0
You can find more information in Gemfile(5) man page here (see 'Platforms' section).
Another approach is to use RUBY_PLATFORM constant:
if RUBY_PLATFORM =~ /win32/
gem "eventmachine", "~> 1.0.0.beta.4.1"
else
gem "eventmachine"
end
I haven't seen full list of available values for RUBY_PLATFORM but you can run
ruby -e 'puts RUBY_PLATFORM'
on both your platforms and see the difference.
You can use the --gemfile option to use different gemfiles for different platforms. See the documentation here
http://gembundler.com/man/bundle-config.1.html
You need multiple versions (all with the same name) of a gem. Therefore, currently with Bundler, you need multiple, simultaneous Bundler dependency snapshot 'lock' files. This is possible, if your developers make use of Bundler's gemfile configuration setting. They might do this either:
By making use of environment variable BUNDLE_GEMFILE (on the command line or in .bash_profile); or
(Probably less desirably) in .bundle/config (globally, in their home directories).
Thus, safely, Bundler can create (and presumably automatically later use, given the same configuration settings) e.g. Gemfile-linux.lock and Gemfile-windows.lock.
Although this basic approach seems workable, it's not very DRY. However, this improves if, e.g., both Gemfile-linux and Gemfile-windows automatically incorporate whatever Gemfile statements they share in common: i.e., if they include the statement:
::Kernel.eval(File.open('Gemfile-common','r'){|f| f.read},::Kernel.binding)

How to use bundler for a project that works in jruby and ruby

How do you use bundler with a project that works for both jruby and ruby?
Specifically, some gems are required in one but not the other, as well as different versions.
Reference: http://github.com/docwhat/iated
You can use:
platforms :ruby do
gem 'gem_that_only_works_with_regular_ruby'
end
platforms :jruby do
gem 'gem_that_only_works_with_jruby'
end

Writing a Jeweler Rakefile that adds dependencies depending on RUBY_ENGINE (ruby or jruby)

I have a Rakefile that includes this:
Jeweler::Tasks.new do |gem|
# ...
gem.add_dependency('json')
end
The gemspec that this generates builds a gem that can't be installed on jruby because the 'json' gem is native.
For jruby, this would have to be:
Jeweler::Tasks.new do |gem|
# ...
gem.add_dependency('json-jruby')
end
How do I conditionally add the dependency for 'json-jruby' when RUBY_ENGINE == 'java'?
It seems like my only option is to manually edit the gemspec file that jeweler generates to add the RUBY_ENGINE check. But I'd rather avoid this, since it kind of defeats the purpose of using jeweler in the first place.
Any ideas?
After some more digging around, I've come to the conclusion that the problem here isn't so much the limitation in Jeweler as it is a problem with how the json-jruby gem is named.
In a perfect world, the json-jruby gem should be named just json. That way when the gem file is built under JRuby (i.e. jgem build json-jruby.gem), the resulting gem file would be named json-1.4.3-universal-java-1.6.gem (RubyGems names the file based on the 'platform' property in the gemspec). When installed with the appropriate platform in the gem name, everything works transparently. There's no need to explicitly require json-jruby. RubyGems uses the appropriate version automatically.
I've contacted the maintainer of the json gem to see if he'd be willing to get json-1.4.3-universal-java-1.6.gem added to his gemcutter repo, but in the meantime you can download the drop-in jruby json gem here: http://roughest.net/json-1.4.3-universal-java-1.6.gem

possible to load nokogiri in jruby without installing nokogiri-java?

i need a way to run following nokogiri script
#parser.rb
require 'nokogiri'
def parseit()
//...
end
and call the parseit() while running below main.rb in jruby
#main.rb
require 'parser'
parseit()
Of course the problem is jruby cannot find 'nokogiri' as I have not installed it aka nokogiri-java via jruby -S gem install nokogiri
The reason is there is some bug I found in nokogiri running under Jruby, so I have only installed nokogiri on Ruby not Jruby. The parser.rb runs perfectly under just Ruby.
So my objective is to be able to run parseit() without having to install nokogiri on Jruby!
Nokogiri works just fine under JRuby (1.4.0 has issues, but the 1.4.1 version of the gem has been working perfect for me).
jruby -S gem install nokogiri
and if you have issues with platform detection you can force it:
jruby -S gem install nokogiri --platform=java
You shouldn't have any issues using it with JRuby, if you are then maybe you're stack isn't right.
Nokogiri should work under FFI in JRuby. See http://www.ruby-forum.com/topic/186274
Nokogiri should just work with JRuby via FFI, so it seems to me that the best course of action is just figure out why installing nokogiri in JRuby doesn't work for you.
What kind of problems you see? What JRuby version? What platform?
Here's an example of a situation where it would appear that the Java implementation of Nokogiri is producing different results from the C version, which is causing the loofah gem to fail a bunch of JRuby tests. This is blocking the ability of the Redmine developers from supporting JRuby.
https://github.com/flavorjones/loofah/issues/88#issuecomment-122747924

Resources