Skip to content

sufleR/embedson

Repository files navigation

Gem Version Dependency Status Code Climate Test Coverage Build Status

Embedson

Main goal is to implement Mongoids embedded document functionality in ActiveRecord.

Hash representation of class defined by specified method (default to_h) is saved in json/hstore column.

Adds functionality of embeds_one to ActiveRecord.

Adds functionality of embedded_in to any class initialized with Hash.

Installation

Add this line to your application's Gemfile:

gem 'embedson'

And then execute:

$ bundle

Or install it yourself as:

$ gem install embedson

Usage

Example with Searchlight is described in blogpost "Persistent queries in Ruby on Rails with PostgreSQL".

Example with Virtus:

	
	#create_tests.rb - migration
	class CreateTests < ActiveRecord::Migration
	  def change
	    create_table :tests do |t|
	      t.json :data
	    end
	  end
	end
	
	class Test < ActiveRecord::Base

	  embeds_one :virt, class_name: Virt,
                        column_name: :data,
                        inverse_of: :parent,
                        hash_method: :to_h    # default option
	end

	class Virt
	  include Virtus.model
	  extend Embedson::Model

	  attribute :name, String
	  attribute :address, Hash

	  embedded_in :parent, class_name: Test, inverse_of: :virt
	end

	virt = Virt.new(name: 'Sample', address: { street: 'Kind', number: '33' })
	virt.attributes # => {:name=>"Sample", :address=>{:street=>"Kind", :number=>"33"}}

	test = Test.create!
	test.attributes # => {"id"=>1, "data"=>nil}

	test.virt = virt
	test.save
	test.attributes # => {"id"=>1, "data"=>{"name"=>"Sample", "address"=>{"street"=>"Kind", "number"=>"33"}}

	test.reload.virt.attributes # =>  {:name=>"Sample", :address=>{:street=>"Kind", :number=>"33"}}
	test.virt == virt # => true
	test.virt.parent == test # => true

You don't have to use all options to define embeds_one and embedded_in. Just name it with downcased related class name.

	#create_tests.rb - migration
	class CreateTests < ActiveRecord::Migration
	  def change
	    create_table :tests do |t|
	      t.json :virt
	    end
	  end
	end

	class Test < ActiveRecord::Base

	  embeds_one :virt
	end

	class Virt
	  include Virtus.model
	  extend Embedson::Model

	  attribute :name, String
	  attribute :address, Hash

	  embedded_in :test
	end

Additional methods in embedded model:

  • ####save Assigns to_h result to parent and saves it with save.

  • ####save! Assigns to_h result to parent and saves it with save!.

  • ####destroy Assigns nil to parent and saves it with save!

  • ####embedson_model_changed! This gem does not provide dirty tracking of embedded model. To register change in parent model use this method in your setter.

	def your_variable=(arg)
	  @your_variable = arg
	  embedson_model_changed!
	end

Known issues

  • Placing initialize method after embedded_in and using Emb.new(parent: parent)

These examples will work:

	class Emb
	  extend Embedson::Model

	  def initialize(attributes = {})
	    # do your work here
	  end

	  embedded_in :parent
	end
	class Emb
	  extend Embedson::Model

	  embedded_in :parent

	  def initialize(attributes = {})
	    self.parent = attributes[:parent]
	    # do your work here
	  end
	end

This will not work!

	class Emb
	  extend Embedson::Model
	  embedded_in :parent

	  def initialize(attributes = {})
	    # if you forget about assigning parent
	    # do your work here
	  end
	end

Contributing

  1. Fork it ( https://github.com/[my-github-username]/embedson/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

License

Copyright (c) 2014 Szymon Frącczak. See LICENSE.txt for further details.

About

Embed class in AR model with Postgresql JSON data type.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages