mongoid_silo 0.0.7 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --color
2
+ --require rspec/instafail
3
+ --format RSpec::Instafail
4
+ --fail-fast
5
+ --drb
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - "1.9.3"
4
+ services: mongodb
5
+ script: bundle exec rspec spec
data/Gemfile CHANGED
@@ -2,3 +2,23 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in mongoid-silo.gemspec
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem 'rspec'
8
+ gem 'factory_girl'
9
+ gem 'database_cleaner'
10
+ gem 'fuubar'
11
+ gem 'faker'
12
+ gem 'spork'
13
+ end
14
+
15
+ group :development do
16
+ gem 'guard'
17
+ gem 'terminal-notifier-guard'
18
+ gem 'guard-rspec'
19
+ gem 'guard-spork'
20
+ gem 'guard-bundler'
21
+ gem 'rb-inotify', :require => false
22
+ gem 'rb-fsevent', :require => false
23
+ gem 'rb-fchange', :require => false
24
+ end
data/Guardfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard :bundler do
5
+ watch("Gemfile")
6
+ end
7
+
8
+ guard :rspec do
9
+ watch(%r{^app/models/(.+)\.rb$}) { |m| "spec/models/#{m[1]}_spec.rb" }
10
+ watch(%r{^app/workers/(.+)\.rb$}) { "spec" }
11
+ watch(%r{^spec/.+_spec\.rb$})
12
+ watch('spec/spec_helper.rb') { "spec" }
13
+ end
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/musicglue/mongoid_silo)
1
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/musicglue/mongoid_silo) [![Build Status](https://travis-ci.org/musicglue/mongoid_silo.png?branch=master)](https://travis-ci.org/musicglue/mongoid_silo)
2
2
  # MongoidSilo
3
3
 
4
4
  MongoidSilo creates and transparently manages static representations of a model - e.g. for creating Feeds or other diverse datastructures.
@@ -27,12 +27,28 @@ Include ```Mongoid::Silo``` in your model, and then declare your silos.
27
27
 
28
28
  ```ruby
29
29
  # The default usage creates a "default" silo, accessable through instance#default_silo that will call
30
- # an instance#to_silo method to populate itself on save.
30
+ # down to the default 'GrainBelt' generator. This will simply store all the attributes on your model,
31
+ # so you almost certainly don't want this. See below for more details.
31
32
  silo
32
33
 
33
- # Or you can specify the silo name and the method that will be called to populate it, like so...
34
- silo :feed, :make_my_feed
34
+ # Or you can specify the silo name and the class that will be called to populate it, like so...
35
+ silo :feed, generator: "MyGeneratorClass"
36
+
37
+ # To create a custom generator class, simply inherit from MongoidSilo::GrainBelt and override the
38
+ # generate method.
39
+ class MyGeneratorClass < MongoidSilo::GrainBelt
40
+ def generate
41
+ {
42
+ name: name,
43
+ age: age,
44
+ dingbats: true
45
+ }
46
+ end
47
+ end
35
48
  ```
49
+ The generator class gets passed the instance of your model when the Silo is generated, and it exposes
50
+ your methods and attributes on that instance. Otherwise, you have access to the instance through the ```object``` accessor.
51
+
36
52
 
37
53
  ## Contributing
38
54
 
@@ -5,33 +5,51 @@ module MongoidSilo
5
5
  class UpdateSiloWorker
6
6
  include Sidekiq::Worker
7
7
 
8
- def perform(item_id, item_class, name, mode="save", method=nil)
9
- @item_id, @item_class = item_id, item_class
8
+ def perform(item_id, item_class, name, mode="save", generator=nil)
9
+ @item_id, @item_class, @generator = item_id, item_class, generator
10
10
 
11
- mode.to_s == "save" ? update_silo(name, method) : destroy_silo(name)
11
+ mode.to_s == "save" ? update_silo(name, generator) : destroy_silo(name)
12
12
  end
13
13
 
14
14
 
15
15
  private
16
- def update_silo name, method
17
- puts "[SILO] Creating or Updating Silo for #{@item_class}::::#{@item_id}"
18
- @item = @item_class.classify.constantize.send(:find, @item_id)
16
+ def update_silo name, generator
17
+ @item = item_class.send(:find, @item_id)
19
18
  @silo = Silo.where(item_class: @item_class, item_id: @item_id, silo_type: name).first
19
+ @content = generator_class.send(:new, @item).generate
20
20
  if @silo
21
- @silo.set(:bag, @item.send(method))
21
+ @silo.set(:bag, @content)
22
22
  else
23
- @silo = Silo.create(item_class: @item_class, item_id: @item_id, bag: @item.send(method), silo_type: name)
23
+ @silo = Silo.create(item_class: @item_class, item_id: @item_id, bag: @content, silo_type: name)
24
24
  end
25
25
  end
26
26
 
27
27
  def destroy_silo name
28
- puts "[SILO] Destroying Silo for #{@item_class}::::#{@item_id}"
29
28
  @silo = Silo.where(item_class: @item_class, item_id: @item_id, silo_type: name).first
30
29
  if @silo
31
30
  @silo.destroy
32
31
  end
33
32
  end
34
33
 
34
+ def item_class
35
+ cl = nil
36
+ @item_class.split("::").inject(nil) do |parent, identifier|
37
+ parent ||= Kernel
38
+ cl = parent.const_get(identifier)
39
+ end
40
+ cl
41
+ end
42
+
43
+
44
+ def generator_class
45
+ cl = nil
46
+ @generator.split("::").inject(nil) do |parent, identifier|
47
+ parent ||= Kernel
48
+ cl = parent.const_get(identifier)
49
+ end
50
+ cl
51
+ end
52
+
35
53
  end
36
54
 
37
55
  end
data/lib/mongoid/silo.rb CHANGED
@@ -5,13 +5,14 @@ module Mongoid
5
5
  extend ActiveSupport::Concern
6
6
 
7
7
  module ClassMethods
8
- def silo name=:default, method=:to_silo
8
+ def silo name=:default, opts={}
9
+ opts[:generator] ||= "MongoidSilo::GrainBelt"
9
10
  define_method "#{name}_silo" do
10
11
  from_silo name
11
12
  end
12
13
 
13
14
  set_callback :save, :after do
14
- update_silo name, method
15
+ update_silo name, opts[:generator]
15
16
  end
16
17
 
17
18
  set_callback :destroy, :after do
@@ -20,36 +21,30 @@ module Mongoid
20
21
  end
21
22
  end
22
23
 
23
- module InstanceMethods
24
- def update_silo name, method
25
- MongoidSilo::UpdateSiloWorker.perform_async(self.id.to_s, self.class.to_s, name, :save, method)
26
- end
27
-
28
- def destroy_silo name
29
- MongoidSilo::UpdateSiloWorker.perform_async(self.id.to_s, self.class.to_s, name, :destroy)
30
- end
24
+ def update_silo name, generator
25
+ MongoidSilo::UpdateSiloWorker.perform_async(self.id.to_s, self.class.to_s, name, :save, generator)
26
+ end
31
27
 
32
- def to_silo #OVERWRITE THIS IN YOUR MODELS, BITCHES
33
- {}
34
- end
28
+ def destroy_silo name
29
+ MongoidSilo::UpdateSiloWorker.perform_async(self.id.to_s, self.class.to_s, name, :destroy)
30
+ end
35
31
 
36
- def from_silo name="default"
37
- if @bag && @bag[name]
38
- @bag[name]
39
- else
40
- @bag = {}
41
- @bag[name] ||= begin
42
- silo = ::Silo.where(item_class: self.class.to_s, item_id: self.id.to_s, silo_type: name).first
43
- silo.bag
44
- rescue Mongoid::Errors::DocumentNotFound
45
- {}
46
- end
32
+ def from_silo name="default"
33
+ if @bag && @bag[name]
34
+ @bag[name]
35
+ else
36
+ @bag = {}
37
+ @bag[name] ||= begin
38
+ silo = ::Silo.where(item_class: self.class.to_s, item_id: self.id.to_s, silo_type: name).first
39
+ silo.bag
40
+ rescue Mongoid::Errors::DocumentNotFound
41
+ {}
47
42
  end
48
43
  end
44
+ end
49
45
 
50
- def json_from_silo
51
- MultiJson.encode from_silo
52
- end
46
+ def json_from_silo
47
+ MultiJson.encode from_silo
53
48
  end
54
49
  end
55
50
  end
@@ -0,0 +1,22 @@
1
+ module MongoidSilo
2
+ class GrainBelt
3
+
4
+ attr_accessor :object
5
+
6
+ def initialize(object)
7
+ @object = object
8
+ end
9
+
10
+ def method_missing(meth, *args)
11
+ object.send(meth)
12
+ end
13
+
14
+ def generate
15
+ out = {}
16
+ object.attribute_names.each do |attribute|
17
+ out[attribute] = object.send(attribute) unless ["_type", "_id"].include?(attribute)
18
+ end
19
+ out
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module MongoidSilo
2
- VERSION = "0.0.7"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/mongoid_silo.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  require "mongoid_silo/version"
2
2
  require 'mongoid_silo/railtie' if defined?(Rails)
3
+ require 'mongoid_silo/grain_belt'
3
4
  require 'mongoid/silo'
4
- require_relative '../app/models/silo'
5
- require_relative '../app/workers/mongoid_silo/update_silo_worker'
5
+
6
+ Dir['./app/**/*.rb'].each{ |file| require file }
6
7
 
7
8
  module MongoidSilo
8
9
  end
@@ -0,0 +1,6 @@
1
+ FactoryGirl.define do
2
+ factory :complex_project do
3
+ name { Faker::Name.name }
4
+ due_date { DateTime.now }
5
+ end
6
+ end
@@ -0,0 +1,7 @@
1
+ FactoryGirl.define do
2
+ factory :multi_silo_project do
3
+ name { Faker::Name.name }
4
+ city { Faker::Address.city }
5
+ country { Faker::Address.country }
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ FactoryGirl.define do
2
+ factory :project do
3
+ name { Faker::Name.name }
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe MongoidSilo::GrainBelt do
4
+ context "Instantiated with a simple model" do
5
+
6
+ before do
7
+ @model = create(:project)
8
+ @silovator = MongoidSilo::GrainBelt.new(@model)
9
+ end
10
+
11
+ it "exposes the model's properties without prefixing" do
12
+ @silovator.name.should eq(@model.name)
13
+ end
14
+
15
+ it "exposes the model through the object accessor" do
16
+ @silovator.object.should eq(@model)
17
+ end
18
+
19
+ it "generates a hash for storing in the silo" do
20
+ @silovator.generate.should be_a(Hash)
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,132 @@
1
+ require 'spec_helper'
2
+
3
+ describe Silo do
4
+
5
+ context 'simple silos' do
6
+ before do
7
+ @project = create(:project)
8
+ end
9
+
10
+ it "should persist a Silo" do
11
+ @project.should be_persisted
12
+ Silo.count.should eq(1)
13
+ end
14
+
15
+ it "should contain the name of the project" do
16
+ @project.default_silo.should eq({"name" => @project.name})
17
+ end
18
+
19
+ it "should update the name if the name changes" do
20
+ @project.name = Faker::Name.name
21
+ @project.save
22
+ @project.default_silo["name"].should eq(@project.name)
23
+ end
24
+
25
+ it "should delete the silo if the project is deleted" do
26
+ @project.destroy
27
+ Silo.count.should eq(0)
28
+ end
29
+
30
+ end
31
+
32
+ context 'Direct finders and methods:' do
33
+ before do
34
+ @project1 = create(:project)
35
+ @project2 = create(:project)
36
+ @project3 = create(:complex_project)
37
+ end
38
+
39
+ it "should find by id and silo type" do
40
+ found = Silo.for_id_and_name_with_no_class(@project1.id.to_s, "default")
41
+ found.should_not be_nil
42
+ end
43
+
44
+ it "should find by id and class and silo type" do
45
+ found = Silo.for_id_and_class_with_name(@project1.id.to_s, @project1.class.to_s, "default")
46
+ found.should_not be_nil
47
+ end
48
+
49
+ it "should find complex documents" do
50
+ found = Silo.for_id_and_class_with_name(@project3.id.to_s, @project3.class.to_s, "complex")
51
+ found.should_not be_nil
52
+ end
53
+
54
+ it "should not find where no match exists" do
55
+ found = Silo.for_id_and_class_with_name("wombats", "aren't", "real")
56
+ found.should be_nil
57
+ end
58
+
59
+ it "should serialize to JSON correctly" do
60
+ found = Silo.for_id_and_class_with_name(@project1.id.to_s, @project1.class.to_s, "default")
61
+ MultiJson.decode("#{found.to_json}").should be_a(Hash)
62
+ end
63
+ end
64
+
65
+ context "Custom Silo constructors:" do
66
+ before do
67
+ @complex_project = create(:complex_project)
68
+ end
69
+
70
+ it "defines an accessor based on the declared silo name" do
71
+ @complex_project.should respond_to(:complex_silo)
72
+ end
73
+
74
+ it "updates a silo on save" do
75
+ @complex_project.name = Faker::Name.name
76
+ @complex_project.save
77
+ @complex_project.complex_silo["name"].should eq(@complex_project.name)
78
+ end
79
+
80
+ it "removes the custom silo on destroying the project" do
81
+ @complex_project.destroy
82
+ Silo.count.should eq(0)
83
+ end
84
+ end
85
+
86
+ context "Multiple silo constructors:" do
87
+ before do
88
+ @multi_silo_project = create(:multi_silo_project)
89
+ end
90
+
91
+ it "Creates two silos" do
92
+ Silo.count.should eq(2)
93
+ end
94
+
95
+ it "Correctly populates the Name silo" do
96
+ _expectation = {
97
+ "name" => @multi_silo_project.name
98
+ }
99
+ @multi_silo_project.name_silo.should eq(_expectation)
100
+ end
101
+
102
+ it "Correctly populates the Location silo" do
103
+ _expectation = {
104
+ "city" => @multi_silo_project.city,
105
+ "country" => @multi_silo_project.country
106
+ }
107
+ @multi_silo_project.location_silo.should eq(_expectation)
108
+ end
109
+
110
+ it "Correctly updates both silos" do
111
+ @multi_silo_project.city = Faker::Address.city
112
+ @multi_silo_project.country = Faker::Address.country
113
+ @multi_silo_project.name = Faker::Name.name
114
+ @multi_silo_project.save
115
+ _name_silo_expectation = {
116
+ "name" => @multi_silo_project.name
117
+ }
118
+ _location_silo_expectation = {
119
+ "city" => @multi_silo_project.city,
120
+ "country" => @multi_silo_project.country
121
+ }
122
+ @multi_silo_project.name_silo.should eq(_name_silo_expectation)
123
+ @multi_silo_project.location_silo.should eq(_location_silo_expectation)
124
+ end
125
+
126
+ it "Destroys both silos when project is deleted" do
127
+ @multi_silo_project.destroy
128
+ Silo.count.should eq(0)
129
+ end
130
+ end
131
+
132
+ end
data/spec/mongoid.yml ADDED
@@ -0,0 +1,9 @@
1
+ test:
2
+ sessions:
3
+ default:
4
+ hosts:
5
+ - localhost:27017
6
+ database: mongoid_silo-test
7
+ options:
8
+ identity_map_enabled: false
9
+ safe: false
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'spork'
4
+ require 'guard/rspec'
5
+ require 'rspec'
6
+
7
+ Spork.prefork do
8
+ require 'mongoid_silo'
9
+ require 'factory_girl'
10
+ require 'database_cleaner'
11
+ require 'faker'
12
+ require 'sidekiq/testing/inline'
13
+ # Loading more in this block will cause your tests to run faster. However,
14
+ # if you change any configuration or code from libraries loaded here, you'll
15
+ # need to restart spork for it take effect.
16
+ FactoryGirl.find_definitions
17
+
18
+ Mongoid.load!(File.expand_path("../mongoid.yml", __FILE__), :test)
19
+
20
+
21
+
22
+ RSpec.configure do |config|
23
+ config.include FactoryGirl::Syntax::Methods
24
+
25
+ config.before(:suite) do
26
+ DatabaseCleaner.strategy = :truncation
27
+ DatabaseCleaner.clean
28
+ end
29
+
30
+ config.after(:each) do
31
+ DatabaseCleaner.clean
32
+ end
33
+ end
34
+
35
+ Dir['./spec/support/**/*.rb'].each{ |file| require file }
36
+ end
37
+
38
+ Spork.each_run do
39
+ Dir['./app/**/*.rb'].each { |file| require file }
40
+ end
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
@@ -0,0 +1,11 @@
1
+ class ComplexProject
2
+ include Mongoid::Document
3
+ include Mongoid::Silo
4
+
5
+ field :name, type: String
6
+ field :due_date, type: DateTime
7
+
8
+
9
+ silo :complex, generator: "MakeComplexGrainBelt"
10
+
11
+ end
@@ -0,0 +1,12 @@
1
+ class MultiSiloProject
2
+ include Mongoid::Document
3
+ include Mongoid::Silo
4
+
5
+ field :name, type: String
6
+ field :city, type: String
7
+ field :country, type: String
8
+
9
+ silo :name, generator: "MakeNameGrainBelt"
10
+ silo :location, generator: "MakeLocationGrainBelt"
11
+
12
+ end
@@ -0,0 +1,9 @@
1
+ class Project
2
+ include Mongoid::Document
3
+ include Mongoid::Silo
4
+
5
+ field :name, type: String
6
+
7
+ silo
8
+
9
+ end
@@ -0,0 +1,8 @@
1
+ class MakeComplexGrainBelt < MongoidSilo::GrainBelt
2
+ def generate
3
+ {
4
+ name: name,
5
+ due_date: due_date
6
+ }
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ class MakeLocationGrainBelt < MongoidSilo::GrainBelt
2
+ def generate
3
+ {
4
+ city: city,
5
+ country: country
6
+ }
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ class MakeNameGrainBelt < MongoidSilo::GrainBelt
2
+ def generate
3
+ {
4
+ name: name
5
+ }
6
+ end
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid_silo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-03 00:00:00.000000000 Z
12
+ date: 2013-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -67,7 +67,10 @@ extensions: []
67
67
  extra_rdoc_files: []
68
68
  files:
69
69
  - .gitignore
70
+ - .rspec
71
+ - .travis.yml
70
72
  - Gemfile
73
+ - Guardfile
71
74
  - LICENSE.txt
72
75
  - README.md
73
76
  - Rakefile
@@ -75,9 +78,23 @@ files:
75
78
  - app/workers/mongoid_silo/update_silo_worker.rb
76
79
  - lib/mongoid/silo.rb
77
80
  - lib/mongoid_silo.rb
81
+ - lib/mongoid_silo/grain_belt.rb
78
82
  - lib/mongoid_silo/railtie.rb
79
83
  - lib/mongoid_silo/version.rb
80
84
  - mongoid_silo.gemspec
85
+ - spec/factories/complex_project_factory.rb
86
+ - spec/factories/multi_silo_project_factory.rb
87
+ - spec/factories/project_factory.rb
88
+ - spec/lib/grain_belt_spec.rb
89
+ - spec/models/silo_spec.rb
90
+ - spec/mongoid.yml
91
+ - spec/spec_helper.rb
92
+ - spec/support/models/complex_project.rb
93
+ - spec/support/models/multi_silo_project.rb
94
+ - spec/support/models/project.rb
95
+ - spec/support/silovators/make_complex_grain_belt.rb
96
+ - spec/support/silovators/make_location_grain_belt.rb
97
+ - spec/support/silovators/make_name_grain_belt.rb
81
98
  homepage: https://github.com/musicglue/mongoid_silo
82
99
  licenses: []
83
100
  post_install_message:
@@ -102,5 +119,18 @@ rubygems_version: 1.8.24
102
119
  signing_key:
103
120
  specification_version: 3
104
121
  summary: MongoidSilo is a bit like a Grain Elevator, but without the grain.
105
- test_files: []
122
+ test_files:
123
+ - spec/factories/complex_project_factory.rb
124
+ - spec/factories/multi_silo_project_factory.rb
125
+ - spec/factories/project_factory.rb
126
+ - spec/lib/grain_belt_spec.rb
127
+ - spec/models/silo_spec.rb
128
+ - spec/mongoid.yml
129
+ - spec/spec_helper.rb
130
+ - spec/support/models/complex_project.rb
131
+ - spec/support/models/multi_silo_project.rb
132
+ - spec/support/models/project.rb
133
+ - spec/support/silovators/make_complex_grain_belt.rb
134
+ - spec/support/silovators/make_location_grain_belt.rb
135
+ - spec/support/silovators/make_name_grain_belt.rb
106
136
  has_rdoc: