3

I had a working (and working well) ImageScience install, that did some simple resizing to various dimensions of images, and then copying them to different directories. All very simple. This small and simple routine was in a rake task. Upon update to Rails 3, this rake task will still work (it does some AR inserts and audio encoding as well), but the image_science require fails with a message like this,

"require on /home//.ruby_inline/Inline_ImageScience_cdab.so failed"

I've ruled out a duff ImageScience install, as I can go into IRB and do some simple calls to ImageScience and make thumbnails. The remainder of the rake task works as well as it did before if I comment out any mention of requiring 'image_science' or the ImageScience routine.

the output from rake on failure is this,

/var/lib/gems/1.8/gems/RubyInline-3.8.6/lib/inline.rb:513:in `load'
/var/lib/gems/1.8/gems/RubyInline-3.8.6/lib/inline.rb:829:in `inline'
/var/lib/gems/1.8/gems/image_science-1.2.1/lib/image_science.rb:90
...
<active_support complaints >
...
/home/<user>/RailsApps/marlow/lib/tasks/flac_import.rake:2
...
<rails complaints>
...
/home/<user>/RailsApps/marlow/Rakefile:7
...
<standard complaints to end>

the Rakefile in the rails app root is a stock and standard Rails 3 Rakefile, like this,

# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.

require File.expand_path('../config/application', __FILE__)
require 'rake'

Marlow::Application.load_tasks

the last line is line 7.

I'm kind of stumped as to what's breaking it, and Google doesn't seem to shed anything. Does anyone know why RubyInline is complaining? Or why this once working Rake task is suddenly unhappy how ImageScience is being called? OS is Ubuntu 10.10, but it was all working prior to the Rails 3 upgrade.

Thanks in advance

4 Answers4

2

This does seem to be the problem, but there is a simpler fix I found from perusing the comments at carlhuda issues 431

I had the same problem and it worked for me. Simply change the require method to be Kernel.require.

After that there's no need to pepper your code with require image_science statements.

Bruno Vieira
  • 3,884
  • 1
  • 23
  • 35
Larry
  • 66
  • 8
  • 1
    I might be wrong, but if the fix is in initializer then you still need to delay image_science require or the fix would not have a chance to apply before the problematic code is used. – artemave Apr 26 '11 at 10:43
1

There is a fix, but you'll need to jump through few hoops.

First delay image_science load:

gem 'image_science', :require => false

Then monkey patch ruby-inline (which image_science relies on). Place this code in config/initializers/ruby_inline_hack.rb:

class Inline::C
  def load
    require "#{so_name}"
    #below is the original version which breaks
    #require "#{so_name}" or raise LoadError, "require on #{so_name} failed"
  end
end

Then require 'image_science' wherever you're using it. And voila.

artemave
  • 6,786
  • 7
  • 47
  • 71
  • many thanks, I'll give this a try anon. I've since "fixed" the matter, by replacing ImageScience with devil (https://github.com/banister/devil). But, I'd like to try this anyway. – CleverCaviar Dec 18 '10 at 10:04
  • so you're just not raising the error -- but how is this a fix? how will it work if the library was not loaded? – Tilo Apr 24 '11 at 16:40
  • the original line is not using short-cut-evaluation! e.g. it should use || instead of "or" – Tilo Apr 24 '11 at 16:47
  • @Tilo: "so you're just not raising the error" exception is raised anyway if require can't load library – artemave Apr 26 '11 at 10:02
  • @Tilo: 'it should use || instead of "or"' either way is the same in this particular case – artemave Apr 26 '11 at 10:04
0

One note on aremave's answer:

It looks like the original code has a bug! It's not using short-cut-evaluation!

class Inline::C
  def load
    require "#{so_name}" || raise LoadError, "require on #{so_name} failed"
  end
end

Notice the || , which will stop the evaluation of the logical expression if the first part is true. If there is an 'or' in the same place, the second part of the expression will always be evaluated, hence the error you're seeing...

Tilo
  • 33,354
  • 5
  • 79
  • 106
  • '...if the first part is true' but it is not necessarily. `require` returns nil/false if gem has already been loaded. – artemave Apr 26 '11 at 10:14
  • You also seem to be confused about difference between `||` and `or`. `or` is `||` with lower precedence. Consider this: `b = nil; a = b or do_stuff` will `do_stuff` and keep `a = nil` whereas `b = nil; a = b || do_stuff` will assign the return value of `do_stuff` to `a` – artemave Apr 26 '11 at 10:25
  • nope, not confused at all about || vs or .. but didn't realize that require can return nil it it's already loaded (and then of course you don't want an error..) – Tilo May 08 '11 at 05:16
  • Ah! I get it. Your version is essentially identical to `require ("#{so_name}" or raise LoadError)` in which case it is also identical to simply `require "#{so_name}"` since `"#{so_name}"` is always true and raise will never happen. – artemave May 08 '11 at 16:20
0

as seen on bundler issue tracker, it worked for me.

Point your gem file to https://github.com/asynchrony/image_science We rebuilt image science without ruby inline.

Thiago Diniz
  • 3,041
  • 5
  • 30
  • 35