Gem Version Dependency Status Code Climate Test Coverage Build Status

Embedson

Adds functionality of embeds_one to ActiveRecord.

Adds functionality of embedded_in to any class:

  • with defined to_h method which should return Hash
  • initialized with Hash.

Result of to_h is saved json/hstore column.

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 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
    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