"resources"-directory for ruby gem
Asked Answered
G

1

6

I'm currently experimenting with creating my own gem in Ruby. The gem requires some static resources (say an icon in ICO format). Where do I put such resources within my gem directory tree and how to I access them from code?

Also, parts of my extension are native C code and I would like the C-parts to have access to the resources too.

Gunthar answered 15/6, 2012 at 13:44 Comment(3)
Ok, I found a way to do it by using FILE from within the ruby code, but this seems rather dirty to me...Gunthar
Yeah, that's what I would have done. There's not really another good way :/ (at least, that I can think of; I could be wrong)Crosshead
Do you want a way to cleanly access the gem's files that are outside of the lib directory, or are you looking for an object-oriented way to work with your resources?Shimmer
S
9

You can put resources anywhere you want, except in the lib directory. Since it will be will be part of Ruby's load path, the only files that should be there are the ones that you want people to require.

For example, I usually store translated text in the i18n/ directory. For icons, I'd just put them in resources/icons/.

As for how to access these resources... I ran into this problem enough that I wrote a little gem just to avoid repetition.

Basically, I was doing this all the time:

def Your::Gem.root
  # Current file is /home/you/code/your/lib/your/gem.rb
  File.expand_path '../..', File.dirname(__FILE__)
end

Your::Gem.root
# => /home/you/code/your/

I wrapped this up into a nice DSL, added some additional convenience stuff and ended up with this:

class Your::Gem < Jewel::Gem
  root '../..'
end

root = Your::Gem.root
# => /home/you/code/your/

# No more joins!
path = root.resources.icons 'your.ico'
# => /home/you/code/your/resources/icons/your.ico

As for accessing your resources in C, path is just a Pathname. You can pass it to a C function as a string, open the file and just do what you need to do. You can even return an object to the Ruby world:

VALUE your_ico_new(VALUE klass, VALUE path) {
    char * ico_file = NULL;
    struct your_ico * ico = NULL;

    ico_file = StringValueCStr(path);
    ico = your_ico_load_from_file(ico_file); /* Implement this */
    return Data_Wrap_Struct(your_ico_class, your_ico_mark, your_ico_free, ico);
}

Now you can access it from Ruby:

ico = Your::Ico.new path
Shimmer answered 15/6, 2012 at 15:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.