RDBMS and Graph Database on the same Rails application - ruby-on-rails

I'm developing a web app that has several "subapps" inside it. For some of them a RDBMS is clearly the weapon of choice. The issue is that lately I came with an idea for a nice little subapp whose logic and performance would benefit greatly from using a graph based database.
My problem is: This subapp is important and graph is the way to make it happen. On the other hand, the others are just fine on a RDBMS and in some cases migrating them to graph would add unnecessary complexity.
So, is it possible to have two heterogeneous database systems running on the same Rails app, perhaps using each controller to specify where to connect?

This is absolutely possible, but it's not something you'd handle at a controller level: it is the responsibility of each model class to define how its data is stored, for example by subclassing from ActiveRecord::Base or including Mongoid::Document or Neo4j::ActiveNode.
There's nothing particular you need to do. As long as the objects all conform to the active model interface (the above all do) then things like link_to 'Person', #person will still work.

Related

Sharing AR models between Rails applications

I have a problem that I have been trying to solve for a while now. I have 4 different Rails applications using the same database, meaning they need to use the same models and have the same migrations. I initially solved the problem by creating a Rails engine packaged into a gem, which then carries all the models and migrations with it. Now I realize that there are pieces of functionality that only one application needs, but the others do not - like for example the admin application needs to have methods for providing sortable tables for all models - the other applications do not need this functionality at all.
So my idea was to find a way where I can provide the "base" models from the gem, while augmenting these base models in my specific applications to add additional functionality when needed. What I tried first was inheritance:
class User < Base::User
end
This does not work though, because now you have 2 User models in your load path (User and Base::User) and when querying associations, it always picks the "closest" class for the associated record class - meaning when you have an Model::Account which belongs_to :user, it will pick Model::User as the association class, not User. I tried reversing the AR type compute method but this only resulted in more problems.
I can technically provide all of my models from the base engine (gem), but the issue here is that how do i extend these models in my application? .class_eval feels really really dirty, inheritance does not work, providing base functionality as mixins means the "base" models do not feel and look like models at all. My goal would be to cause as little friction as possible for the other developers, I want them to be able to define their models in the gem like they do normally and then also have an easy way to extend that functionality in other applications.
Has anyone solved this problem before or have any suggestions? Or how do you guys solve this problem in your larger applications? Any help would be appreciated.
This is mentioned in the Rails guides. It describes class modification with the Decorator pattern.

In-memory ActiveRecord for production use

I'm currently extending some functionality from Redmine 1.4 issue tracker (it uses Rails 2.3.14 and Ruby 1.8.7).
One thing I don't really like about it for my current use case is that some classes that encapsulate business logic (roles, workflows) are database based instead of code based - our customer shouldn't be able to change roles and workflows without our intervention, and while I could just preload a pre-baked set of db data with the roles and workflows I want, I still think it would be a solution which is not the best for maintainability's sake.
What I'd like to do is something like that:
class Person < SomeInMemoryActiveRecordBaseClass
end
p = Person.new(:name => "Somebody)
p.save
And then I'd like to be able to invoke ActiveRecord methods on any Person object and from the Person class, even though there's no real database behind it.
This may seem a silly thing to do (If I were creating the project from scratch I'd simply not use an AR-based object, but since I'm building on something that already exists this is not an option), but the objects I need to work with in-memory are used in plenty of places and they're supposed to be AR-based; changing their usage everywhere would really be time consuming.
I've seen some projects, like nulldb, which are test-oriented, not production-oriented, and they don't implement all methods. Besides that, the AR interface seems quite sql-oriented and I don't know if it's really feasible to get an sql-emulation layer "right".
Is there any library that could suit my use-case of creating a fully-functional activerecord in-memory database?
(I've already thought about using a different connection and leveraging an inmemory sqlite db, but it seems a bit overengineered to me).

Building consumable uri/urls for a model (rails/datamapper/SOA)

Perhaps you can help me think this through to greater detail.
I need to build or make available a uri for a model instance that can be referenced or used by another application which may or may not be a rails application.
e.g.
I create a standard Post with content; I want to build a URL for that post another application can consume or reference by looking at the model in the database (or another less sticky fashion). Datamapper has a URI field, I want to build a canonical uri, store it there and have another application be able to access, announce, manipulate, etc.
Basically, I have several applications that may be in different places, that need to access the same model, to do differing things with the model. I need a way to make that happen clearly without putting them all in one monster application.
I've looked at Pubsubhub, RSS, etc. but haven't found any concrete examples of what I'm trying to do. Do I need to create an common API for the applications, etc?
DataMapper is very flexible about using existing databases.
Many people come to DataMapper because it can create and tear down the database structures without migrations. However, you do not have to work with it in that way.
I have had good success with using a large set of models owned by a central 'housekeeping' app and then declaring a small subset of the same models in separate 'interface' apps.
Some trial and error is required to figure out what works but it can certainly be done. I'd suggest putting your models in modules and including them across apps if possible.
A final point it sounds like you want URIs/URLs to be the primary interface. If that is the case I strongly suggest you look at Sinatra. It is entirely oriented around URLs (and I find Rails routes very obtuse).

One model - many DB connections in Rails?

(using Ruby on Rails and ActiveRecord)
In short: Is there some way how a model can use different DB schema for each request?
Why I need id: I have a working intranet application working for one company but I decided I would like to offer it to other companies. The Rails way would be to add company_id to each model and alway use this scope. But making separate DB schema for each company would make much more sense. Is there some standard way how to do it?
thanks!
What would be wrong with having a separate instance of your application for each company?
Adding company_id to all the models is absolutely the way to go. What you're talking about is very difficult to manage in the long haul, and it may be tricky to ensure the correct connection is used to store the correct data.
Although layering in differentiation like that is annoying, it can be done and proven in a fairly short period of time, and after that things will be easier to manage. With named_scope it is not hard to filter using attributes like that.
The simple alternative is to deploy the application more than once, with a different database.yml for each company, where the data is isolated on the application level, not within the application.
It would be easy to do this with Passenger (mod_rails) and a bit of shell scripting.

Non persistent data in a Rails app

I'm working on an "analytics" page for a rails app. The analytics page does not persist any data of its own (it's very primitive at this point) but does utilize metrics that I'm grabbing from the DB (via the aggregate expressions built into ActiveRecord). Aside from gathering and presenting the metrics the only other requirement I have is to allow the user to provide a date range to filter the data. Up to this point I have been using instance variables and the like to store the metrics information...as the number of metrics grow along with the need to manage the start and end filter dates I begin thinking that I should put this data into its own model. If I do move all of my "data" into a model should I just use a plain object with attr_accessors or is there a more appropriate base class I could use for non-persistent data? I'm familiar enough with a MVC architecture to know that my controller is getting to bloated but no familiar enough with rails to determine how I should organize my data/logic in this case.
Any insight would be greatly appreciated!
It sounds like you could use a Rails non active-record model. There's a good Railscast about that :
http://railscasts.com/episodes/121-non-active-record-model
Hope that helps,
You're on the right track here. Many applications have classes inside app/models that do not inherit from ActiveRecord::Base. Any time you find yourself managing lots of arbitrary variables inside controller actions, it's a good place to consider abstracting that data into a non-persistent model.
This is an area that's not well documented at present, probably because the ActiveRecord stuff is sexier?
I went through the same process, finding my controller actions were becoming uncomfortably large and full of logic as I strove to construct my derived data from ActiveRecord-based models, which in turn started to acquire additional responsibilities that they didn't really want or need.
Once I got the same advice you're getting now the whole thing simplified magnificently.

Resources