I've written a sprockets processor for losslessly compressing jpgs and pngs, you check it out it here: https://github.com/botandrose/sprockets-image_compressor
However, I can't use this gem on heroku, because the jpegoptim and pngcrush programs aren't available within their environment. Furthermore, users of the gem will need to remember to install these programs on every system they want to use my gem. So, I think it'd be nice if I could vendor in these binaries as a fallback if the system doesn't have them installed already.
So, is this totally crazy? Would I need to provide a 64bit binary as well as a 32bit? Would I still require some sort of external library to be installed? Would I be better off writing some sort of C extension that hooks into these programs?
I haven't seen many gems in the wild that do this sort of thing. One other option, however, is to provide rake tasks that go out and fetch the programs if they aren't already installed on the machine. It might be tricky to make it work for all the different platforms, though.
With regard to using your gem on Heroku: remember that Heroku has a read-only filesystem (except for the /tmp directory), so running Sprockets processors like yours on Heroku isn't really a practicable option anyways. I personally just use rake assets:precompile and commit all the precompiled assets to my Git repo before pushing to Heroku. Yes, I know it messes up the repo history, but it's the easiest way to go (at least for now). Hopefully Heroku will come up with some other option in the future.
As far as the main question you asked, hopefully someone else can provide a good answer. Your project looks very cool; I am just going to try it out.
Related
I have done a bit of digging through the rubygems code and it doesn't look like there is a built-in way to get it to not throw a Gem::ConflictError even if there is one. During development I might be wanting to test something that I know is not going to touch the code from which the conflict is coming or I know that the whatever version of the erstwhile conflicting gem isn't going to cause a problem. I just want to get on with testing what I want to test and I'll worry about version conflicts later.
I know I can hack rubygems to do this. I can think or multiple ways to get it done. I'm just kind of curious if anyone has already done this, how they did it, and maybe if that code has been shared somewhere. I'm also a bit curious as to why this isn't built in to rubygems as a development tool.
You need to worry about version conflicts now before you can get anything done. As Ruby has a singular root namespace and every dependency gets loaded there it's generally not possible to load multiple versions of the same gem. Other systems like NPM for Node.js are significantly more flexible, it's possible to load any number of versions at the same time, so if you're used to that you'll need to adjust your expectations.
If you're trying to do testing and you want to avoid resolving a conflict, just remove that gem requirement from the Gemfile temporarily.
Ultimately you'll have to fix things, there's no way around it, but you can always be selective about what you require.
If you really know what you are doing, try this:
export NOEXEC_DISABLE=1
ruby you-program.rb
This environment variable will disable search and check for Gemfiles and gem versions.
My Rails site uses a certain gem which is really not very good. Every time I need to do something new I end up having to spend as much time adding features to the gem as I do adding code to the actual Rails project. But I don't mind, and I have my Gemfile set up to point to my GitHub fork of the gem (I tried submitting PRs, but the maintainer seems to have stepped down).
The problem is that I really haven't found a sane way of testing new things I add to the gem. It'd be especially nice to test it within rails c, but the only ways I can think of doing that are a) Changing ~/.rvm/gems/.../foo.rb, which doesn't seem right or b) Bumping the version, pushing to Github, and running bundle up, which in addition to being time-consuming is obviously a disaster since I don't know for sure whether the commits I make are right or not.
I'd even be perfectly happy with a standard irb. But various permutations of require lib/foo from within the gem's directory don't work.
So what's the best practice here?
If you are using a gem and working on it at the same time, the best way is to use Bundler and provide a local path:
gem 'my_bad_gem', path: '../my_bad_gem/'
This will look for the gem under the given (relative in this case) path. Another option is to use local git repositories (see http://bundler.io/v1.3/git.html).
After years of being away from Ruby, I'm back full-force and have just cut my first gem, which includes an executable. Everything works like a charm.
The problem I am facing, however, is that I ALSO have a startup script (not part of the gem istelf) that daemonizes the executable. Additionally, I'd also like for the startup script to point the executable at configuration in a place like /var/
To the best of my knowledge, there's no way with rubygems, gemspec, etc., to specify files getting blown out to other parts of your system during install (e.g. startup script to /etc/init.d, and config to /var/). It certainly wouldn't make sense if you COULD do that.
So... my question is... what IS the proper procedure for automating the installation of something like this. I'm using RHEL, and am wondering if it's, perhaps, time for me to get my feet wet with making my first RPM.
Any thoughts?
You can do it. However it is probably not quite the recommended approach. But yes it is possible to run arbitary code during gem installation using the extensions option.
From the RubyGems Manual:
Usage
spec.extensions << 'ext/rmagic/extconf.rb'
Notes
These files will be run when the gem is installed, causing the
C (or whatever) code to be compiled on the user’s machine.
Just place whatever ruby code you need into the extconf.rb (or equivalent) file.
Examples for building C-extensions from the RubyGems Guides:
http://guides.rubygems.org/c-extensions/
I've got a ruby web app that uses lilypond to generate sheet music based on user input. I'd like to move the hosting to heroku (I've recently used heroku on a few projects and really liked it, plus my traffic is low enough that it'd be free host it on heroku, for a while at least). However, heroku's dyno architecture doesn't allow you to ssh in and install whatever packages you want...instead, you give it a gems manifest, and it will install the gems for you.
So, if I'm going to deploy to heroku, I'm going to need to package lilypond as a gem. I've released a few pure-ruby gems, but haven't dealt with native extensions or precompiled binaries, or anything like that.
Is it possible to take some precompiled binaries and package it inside a gem? Ideally, this would include binaries for OS X (which I develop on) and debian linux (which is what's running on heroku), and would install the proper binary when the gem was installed.
it is possible, since precompiled binary gems for windows are the norm. Take a look at rake compiler, perhaps.
also https://github.com/rdp/ruby_tutorials_core/wiki/gem (https://en.wikibooks.org/wiki/Ruby_Programming/RubyGems) might help
-r
I think you've got a few options here:
You could get the Lilypond source and package it into a gem with a native C extension. There are some useful guides on how to do that at http://guides.rubygems.org/c-extensions/ and http://patshaughnessy.net/2011/10/31/dont-be-terrified-of-building-native-extensions
There's also a gem called gitara but I haven't been able to find any information about using it on Heroku. It might be worth emailing the author and asking if he knows anything about that.
You could create a Heroku buildpack that installs Lilypond as part of your deployment. I wasn't able to find any for Lilypond, but there are plenty of examples that do similar things - for example, this one installs Imagemagick (which is included by default on Heroku, so probably not necessary anymore - but hopefully the code is helpful). More documentation at https://devcenter.heroku.com/articles/buildpack-api and https://devcenter.heroku.com/articles/buildpack-binaries
Based on my reading, I think the buildpack option is the best way to go.
Hopefully this helps!
Instead of precompiling, you should be able to just list the gem in your .gems file, see the Heroku documentation. Of course, this requires your gem builds the native code correctly - this is still a task, but hopefully an easier one.
Me and my team are starting to build up a few re-usable scripts. They're re-usable within our org only as they work with proprietry apps and our particular server environment. So not really suitable for rubyforge or github, etc.
My question is, what is the best practice for ensuring we're all using the latest and greatest scripts across all users? We pretty much run these scripts on one server, but may need to expand to others.
Should we bundle them into gem(s) and start a private gem server?
Or something simpler like a common, shareable lib directory. Perhaps with a script to download/update from our SCM?
Other ideas?
Thanks....
This depends on some factors, like how many people want to change the code (only your team, or someone else too), or how much money you have for this?
Personally I'd create a build+gem server, where you can upload the scripts using some versioning system (like git or svn, depends on how many people are working on the project), and then create a cron job, that would automatically genereate the gems from the sources at generic intervals and store them as different versions. This way you can be sure that you always have an authorative server that stores your applications gems, and you can always get an earlier version if something breaks. Your script might create separate gem version names, like "appserv-edge" or "appserv-stable"
You might also want to check out github's closed source options too, if you have the money to afford that. I don't know however whether they have gem building and hosting facilities for non open-source programs.
I've created a private gemserver and it's dead easy. The only tricky bit is deciding how you want your users to upload gems. Personally, I just use a PHP upload form, and have it check to make sure that it's not masking any existing gems.
At my office we're using a bit of a hybrid approach for some of our shared scripts and libs. We do bundle them all in to a gem, but rather than using a gem server we keep them in source control, and then build the gem (using newgem) and install it locally as necessary.
The downside of this approach is that it takes two commands instead of one to install the gem, but this is largely mitigated in qa and production environments, since we use Capistrano for deployment.
The upsides are that it's dead simple, and in development there is a very short edit/build/deploy cycle if you're working with something that requires changes to the gem. I'm currently pulling a lot of common functionality in to the shared gem, so I'm really appreciating that aspect.