Writing Gems for Rails application - ruby-on-rails

I want to write a gem that adds some functionalities to MyController in a Rails application. Basically I know how to write a gem, I have already wrote a couple of gems, used them in my Ruby applications. They work fine. But I have never written gems that deals with Rails classes or objects, in particular Controller classes.
I understand that Rails applications are Ruby applications, but it is at the same time a framework with a lot of out-of-box modules, classes, objects, and underlying structures and conventions.
So, is there any rules/standards/convention that one should follow when writing a gem to use it in Rails application? Maybe best practices?

Related

Adding HTML to a Ruby on Rails Gem

I'm not a RoR expert, trying to write my first gem which includes javascript, erb, etc. Is this possible, it seems like every tutorial and example code I can find only includes ruby code. If it is possible, what does the directory structure of the gem look like with javascript and erb files? Thanks.
What you want is an engine.
Engines can be considered miniature applications that provide
functionality to their host applications. A Rails application is
actually just a "supercharged" engine, with the Rails::Application
class inheriting a lot of its behavior from Rails::Engine.
Therefore, engines and applications can be thought of almost the same
thing, just with subtle differences, as you'll see throughout this
guide. Engines and applications also share a common structure.

Creating Rails Gems

I want to build my application in a modular way: For example I might have:
Users->has_and_belongs_to_many->Projects
Users->has_and_belongs_to_many->Tasks
Projects->has_many->Tasks
Tasks->belongs_to->Project (1 task belongs to 1 project.)
Note: Projects AND tasks can have many users.
The way I was thinking of building this is by doing:
User = Gem
Projects = Gem
Tasks = Gem
Each can return either json (for ember) or html. Neither depend on each other, The idea is that each is just a detail. Rails, ember and html are all just details.
How could I go about this and at the end of the day hook them together like a puzzle? or is this even feasible?
Right now I have the user piece of this concept almost done. It contains models, tests, controllers and views. Can I bundle that as a gem or should I only bundle the controller and the models? This "User" gem would make use of friendlyId gem to make the urls look nice, infact all the "gems" (project, tasks and users) will depend on this gem.
What would you recommend to do to have the kind of modularity I want? is it good practice? bad practice?
Pivotal Labs made a presentation (Euruko 2013 in Athens) and they showed a rails engines approach similar to what you are describing. Here is the presentation http://www.ustream.tv/recorded/35107339/highlight/377037
I haven't seen it in practice though, but I would like to.
I believe use of Rails engines is the way to go.
Each Engine can be an app in itself.
For instance Devise - gem that adds a lot of authentication functionality into your app is a Rails Engine. It provides its own controllers, helpers, mailers and views that you can use from your app.
I personally was working in projects that were using Engines to plugin i18n web backends (admin page that allows entering and saving translations to Redis) into many apps and to plugin users' bug reports and Question&Answer functionality into several existing projects.
Each engine is being included in a project as a gem, it can consist of anything that normal app does - controllers, views, models, assets, other gems...
I personally haven't heard of any success stories with such approach (but I don't know if anyone tried though), so if you have a solid concept in mind maybe it will work for you.

Could someone please define an Engine in Ruby in Rails?

In computing terms, an engine is something that is continually producing output based on input. But in Ruby, the term seems a little bit loose. The people who've created Refinery CMS have taken to calling gems that extend the functionality of their system, 'engines'.
Basically, what I want to know is, is Spree, the open source ecommerce cms written in ruby, an engine? Would calling it the 'spree engine' be correct?
As defined by Rails, an Engine is a lot like an application within an application. Spree is one of these, and there are others. Each engine has its own app folder with the same sort of structure you'd see in a top-level application.
You can combine one or more engines together into an application, then add your own functionality on top. That's what makes systems like Spree far more flexible than a fixed-puropose Rails app that you have limited control over.
Things that extend Rails are only truly engines if they are self-contained applications. Many gems add functionality that's much more specific than that, so are better termed "plug-ins" or "modules" depending on the phrasing.
It's actually pretty easy to build your own engine and can be useful for separating and re-using code across several different applications.
I think that there is quite good explanation in guide Getting Started with Engines.
Spree is actually comprised of many engines...
The overcooked version: Engines come kitted with (many of) the guts of a typical rails application, with a few bonuses: namespacing out of the box, generators for easily copying migrations, and the ability to mount it in another rails application.
From http://guides.rubyonrails.org/engines.html
1 What are engines?
Engines can be considered miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the Rails::Application class inheriting a lot of its behavior from Rails::Engine.
Try to read this guide: http://guides.rubyonrails.org/engines.html and also this cast: http://railscasts.com/episodes/277-mountable-engines

Packaging Rails 2.3 Models

I've got an existing webapp running on Rails. The plan is to setup a new server which will provide an API service, and eventually update the webapp to be a client of this API.
It seems like a good approach to achieving this would be packaging all the models as gems and sharing them between the two applications. Eventually the API service would be monolithic - containing all the models, but there is a period of development/migration where models will need to be shared.
Both the API and the webapp will be using the same database.
What do I need to consider before jumping into packaging up all my
models?
Would it be worthwhile to package all the models into a
single gem, individually package each model, or do some sort of
logical grouping of models?
How would I approach dependencies for
gems?
For reference, here's a similar-ish question:
Sharing models between Rails apps using gems
I'm also just getting familiar with packaging Ruby code as a Rubygem. (This might explain some of my questions above.)
[edit] I'm using Rails 2.3.14, not Rails 3.X.
We have done packaging models to a gem in the past. We started out by moving a group of models that are associated with each other but have no other dependency of the rest of the models. Then we slowly move another group. It is a bit painful but we eventually did it. The model gems are shared among several apps.

Can you in any way interface Ruby Gems with PHP, Python, etc.?

Stupid question, and forgive me for asking, but someone is asking me, and I am not a super expert with Rails yet.
Suppose I have some Rails gem I write. Now suppose a customer has some other framework, like Django or CakePHP, and I want to provide the functionality offered by my gem (eg. CRUD for automotive data) to them as a module in their framework. Could I somehow make it so they could interface my gem with Django or CakePHP?
Obviously I could do something with some API magic--and I'll probably end up going that route. But I just want to know whether there is a way to directly interface with Gems from a non-Rails application.
Not really. Gem's are by their very nature Ruby. They of course don't need to be for a Rails application they can be used with any ruby program you write, but really are the preferred method of packaging ruby libraries and programs.
Alternatively if the Ruby Gem in question is executable and your Ruby Gem's path is in your shell's path variable you can executed the gems binary like any command line tool and thus use it with anything.
Like like how Rails gives you the rails command.

Resources