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 withsave
. -
####save! Assigns
to_h
result to parent and saves it withsave!
. -
####destroy Assigns
nil
to parent and saves it withsave!
-
####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 afterembedded_in
and usingEmb.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
- Fork it ( https://github.com/[my-github-username]/embedson/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
License
Copyright (c) 2014 Szymon FrÄ…cczak. See LICENSE.txt for further details.