Last Updated: February 25, 2016
·
2.471K
· mfpiccolo

Using Rails with Postgres for schemaless data

Rolling your own integration with an external service where the schema can change from moment to moment can be tough.

I was building an app that relied on salesforce data from multiple salesforce accounts. Not only did we know nothing about the data as we pull it in from the external service, salesforce data structure can be changed at any moment by the users! That scares the hell out of us Rails developers who are used to using structured databases.

I came up with a solution that creates pliable active record objects by using JSON data store in Postgresql.

I extracted this out into a gem called pliable.

With pliable you get several niceties.

Here is the Ply model your generator created with rails g pliable:model. The generator also creates and runs the migration for the "plies" table for you.

class Ply < Pliable::Ply
  # Define methods here that you want all you Ply backed models to have.
end

Now you can create a model that is backed by Ply.

class Foo < Ply
  ply_name "Foo"
  # Define methods that you only want Foo to have.
end

Now lets make another Ply Backed Model.

class Bar < Ply
  ply_name "Bar"
end

Now you should be able to treat these like any other Active Record object with the added bonus of a
few features. You can assign any json data to the data attribute.

foo = Foo.create(data: {"some" => "json", "other" => "data"})

The nice part is now these json keys are methods.

foo.some => "json"

Another nicety is associations. You can associate a Ply inhereted class to another using parent
and child relationships and the PlyRelations model. There is no need to define the relationship. Pliable will handle this part if you create the relationship.

foo = Foo.create
bar = Bar.create
PlyRealation.create(parent_id: foo.id, parent_type: foo.class.name, child_id: bar, child_type: bar.class.name)

foo.bars => <#<ActiveRecord::AssociationRelation [#<Pliable::Ply id: 2 otype: "Bar" ...>