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.