stratify-base 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +52 -0
- data/LICENSE +20 -0
- data/README.md +21 -0
- data/Rakefile +10 -0
- data/lib/stratify/activity.rb +33 -0
- data/lib/stratify/archiver.rb +45 -0
- data/lib/stratify/collector.rb +100 -0
- data/lib/stratify/collector_coordinator.rb +13 -0
- data/lib/stratify/field_definition.rb +15 -0
- data/lib/stratify/logger.rb +14 -0
- data/lib/stratify/mongoid_extension.rb +38 -0
- data/lib/stratify/renderable.rb +41 -0
- data/lib/stratify/version.rb +5 -0
- data/lib/stratify-base.rb +4 -0
- data/spec/mongoid.yml +3 -0
- data/spec/prototypes/bacon.rb +46 -0
- data/spec/spec_helper.rb +48 -0
- data/spec/stratify/activity_spec.rb +55 -0
- data/spec/stratify/archiver_spec.rb +85 -0
- data/spec/stratify/collector_coordinator_spec.rb +41 -0
- data/spec/stratify/collector_spec.rb +125 -0
- data/spec/stratify/field_definition_spec.rb +29 -0
- data/spec/stratify/integration_spec.rb +31 -0
- data/spec/stratify/mongoid_extension_spec.rb +80 -0
- data/spec/stratify/renderable_spec.rb +53 -0
- data/stratify-base.gemspec +29 -0
- metadata +158 -0
data/.gitignore
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm use ruby-1.9.2-p180@stratify
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
stratify-base (0.1.0)
|
5
|
+
bson_ext (~> 1.3.1)
|
6
|
+
mongoid (~> 2.0.2)
|
7
|
+
tilt (~> 1.3.2)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activemodel (3.1.0.rc1)
|
13
|
+
activesupport (= 3.1.0.rc1)
|
14
|
+
bcrypt-ruby (~> 2.1.4)
|
15
|
+
builder (~> 3.0.0)
|
16
|
+
i18n (~> 0.6.0beta1)
|
17
|
+
activesupport (3.1.0.rc1)
|
18
|
+
multi_json (~> 1.0)
|
19
|
+
bcrypt-ruby (2.1.4)
|
20
|
+
bson (1.3.1)
|
21
|
+
bson_ext (1.3.1)
|
22
|
+
builder (3.0.0)
|
23
|
+
database_cleaner (0.6.7)
|
24
|
+
diff-lcs (1.1.2)
|
25
|
+
i18n (0.6.0)
|
26
|
+
mocha (0.9.12)
|
27
|
+
mongo (1.3.1)
|
28
|
+
bson (>= 1.3.1)
|
29
|
+
mongoid (2.0.2)
|
30
|
+
activemodel (~> 3.0)
|
31
|
+
mongo (~> 1.3)
|
32
|
+
tzinfo (~> 0.3.22)
|
33
|
+
multi_json (1.0.3)
|
34
|
+
rspec (2.6.0)
|
35
|
+
rspec-core (~> 2.6.0)
|
36
|
+
rspec-expectations (~> 2.6.0)
|
37
|
+
rspec-mocks (~> 2.6.0)
|
38
|
+
rspec-core (2.6.3)
|
39
|
+
rspec-expectations (2.6.0)
|
40
|
+
diff-lcs (~> 1.1.2)
|
41
|
+
rspec-mocks (2.6.0)
|
42
|
+
tilt (1.3.2)
|
43
|
+
tzinfo (0.3.27)
|
44
|
+
|
45
|
+
PLATFORMS
|
46
|
+
ruby
|
47
|
+
|
48
|
+
DEPENDENCIES
|
49
|
+
database_cleaner (~> 0.6.7)
|
50
|
+
mocha (~> 0.9.12)
|
51
|
+
rspec (~> 2.6.0)
|
52
|
+
stratify-base!
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Jason Rudolph (http://jasonrudolph.com)
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
'Software'), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# stratify-base
|
2
|
+
|
3
|
+
## Dependencies
|
4
|
+
|
5
|
+
Stratify is developed and tested with the following dependencies.
|
6
|
+
|
7
|
+
* Ruby 1.9.2 (See `.rvmrc` for the specific version.)
|
8
|
+
* MongoDB 1.8
|
9
|
+
|
10
|
+
## Development
|
11
|
+
|
12
|
+
To get set up for development on stratify-base, clone the repo, and ...
|
13
|
+
|
14
|
+
cd stratify/stratify-base
|
15
|
+
gem install bundler
|
16
|
+
bundle
|
17
|
+
rake
|
18
|
+
|
19
|
+
## License
|
20
|
+
|
21
|
+
Copyright 2011 Jason Rudolph ([jasonrudolph.com](http://jasonrudolph.com)). Released under the MIT license. See the LICENSE file for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
require 'stratify/mongoid_extension'
|
3
|
+
require 'stratify/renderable'
|
4
|
+
|
5
|
+
module Stratify
|
6
|
+
class Activity
|
7
|
+
include Mongoid::Document
|
8
|
+
include Mongoid::Paranoia
|
9
|
+
include MongoidExtension::NaturalKey
|
10
|
+
include Renderable
|
11
|
+
|
12
|
+
store_in :activities
|
13
|
+
|
14
|
+
field :source, :type => String
|
15
|
+
field :created_at, :type => DateTime
|
16
|
+
|
17
|
+
validates_presence_of :created_at
|
18
|
+
|
19
|
+
def permalink
|
20
|
+
nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def created_on
|
24
|
+
return nil unless created_at
|
25
|
+
created_at.to_date
|
26
|
+
end
|
27
|
+
|
28
|
+
def duplicate?
|
29
|
+
duplicate_activities = self.class.where(natural_key_hash)
|
30
|
+
duplicate_activities.exists? || duplicate_activities.deleted.exists?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'stratify/logger'
|
2
|
+
|
3
|
+
module Stratify
|
4
|
+
class Archiver
|
5
|
+
attr_reader :collector
|
6
|
+
|
7
|
+
def initialize(collector)
|
8
|
+
@collector = collector
|
9
|
+
end
|
10
|
+
|
11
|
+
def run
|
12
|
+
collect_activities
|
13
|
+
ensure
|
14
|
+
record_collection_statistics
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def collect_activities
|
20
|
+
collector.activities.each do |activity|
|
21
|
+
document_activity_source(activity)
|
22
|
+
persist_activity(activity)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def document_activity_source(activity)
|
27
|
+
activity.source = collector.source
|
28
|
+
end
|
29
|
+
|
30
|
+
def persist_activity(activity)
|
31
|
+
# Since we run the collectors frequently, it is very common to encounter
|
32
|
+
# objects that we have already imported. If this activity is a duplicate
|
33
|
+
# of an existing object, then we skip importing this activity.
|
34
|
+
return if activity.duplicate?
|
35
|
+
|
36
|
+
unless activity.save
|
37
|
+
Stratify.logger.error("Failed to persist activity: #{activity}.\nValidation errors: #{activity.errors}")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def record_collection_statistics
|
42
|
+
collector.update_attribute :last_ran_at, Time.now
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
require 'stratify/archiver'
|
3
|
+
require 'stratify/field_definition'
|
4
|
+
|
5
|
+
module Stratify
|
6
|
+
class Collector
|
7
|
+
include Mongoid::Document
|
8
|
+
|
9
|
+
store_in :collectors
|
10
|
+
|
11
|
+
field :last_ran_at, :type => DateTime
|
12
|
+
|
13
|
+
def self.configuration_fields(fields_hash = nil)
|
14
|
+
@configuration_fields = initialize_configuration_fields(fields_hash) unless fields_hash.nil?
|
15
|
+
@configuration_fields || []
|
16
|
+
end
|
17
|
+
|
18
|
+
def configuration_fields
|
19
|
+
self.class.configuration_fields
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.configuration_instructions(instructions = nil)
|
23
|
+
@configuration_instructions = instructions unless instructions.nil?
|
24
|
+
@configuration_instructions
|
25
|
+
end
|
26
|
+
|
27
|
+
def configuration_instructions
|
28
|
+
self.class.configuration_instructions
|
29
|
+
end
|
30
|
+
|
31
|
+
def configuration_summary
|
32
|
+
return nil if configuration_fields.empty?
|
33
|
+
read_attribute(configuration_fields.first.name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
Archiver.new(self).run
|
38
|
+
end
|
39
|
+
|
40
|
+
# To be implemented by subclasses
|
41
|
+
#
|
42
|
+
# Returns a collection of activities to be saved.
|
43
|
+
def activities
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
|
47
|
+
# Define where this collector's activities originate from (e.g., "Twitter", "iTunes")
|
48
|
+
def self.source(src = nil)
|
49
|
+
@source = src unless src.nil?
|
50
|
+
@source
|
51
|
+
end
|
52
|
+
|
53
|
+
def source
|
54
|
+
self.class.source
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.sources
|
58
|
+
unsorted_sources = Collector.collector_classes.map(&:source)
|
59
|
+
unsorted_sources.sort_by {|source| source.downcase}
|
60
|
+
end
|
61
|
+
|
62
|
+
class << self
|
63
|
+
attr_reader :collector_classes
|
64
|
+
end
|
65
|
+
|
66
|
+
@collector_classes = []
|
67
|
+
|
68
|
+
def self.inherited(subclass)
|
69
|
+
super
|
70
|
+
Collector.collector_classes << subclass
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.collector_class_for(source)
|
74
|
+
Collector.collector_classes.find {|clazz| clazz.source == source}
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def self.initialize_configuration_fields(fields_hash)
|
80
|
+
field_definitions = objectify_fields(fields_hash)
|
81
|
+
apply_fields_to_class(field_definitions)
|
82
|
+
field_definitions
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.objectify_fields(fields_hash)
|
86
|
+
fields_hash.map do |f|
|
87
|
+
name = f[0]
|
88
|
+
attributes = f[1]
|
89
|
+
Stratify::FieldDefinition.new(name, attributes)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.apply_fields_to_class(field_definitions)
|
94
|
+
field_definitions.each do |field|
|
95
|
+
field field.name
|
96
|
+
validates_presence_of field.name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Stratify
|
2
|
+
class CollectorCoordinator
|
3
|
+
def self.run_all
|
4
|
+
Stratify::Collector.all.each do |collector|
|
5
|
+
begin
|
6
|
+
collector.run
|
7
|
+
rescue => e
|
8
|
+
Stratify.logger.error("Error running collector. Collector => #{collector}. Error => #{e}")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Stratify
|
2
|
+
class FieldDefinition
|
3
|
+
attr_reader :name, :type, :label
|
4
|
+
|
5
|
+
def initialize(name, attribute_hash)
|
6
|
+
@name = name
|
7
|
+
@type = attribute_hash[:type]
|
8
|
+
@label = attribute_hash[:label]
|
9
|
+
end
|
10
|
+
|
11
|
+
def label
|
12
|
+
@label || @name.to_s.titleize
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Stratify
|
2
|
+
module MongoidExtension
|
3
|
+
module NaturalKey
|
4
|
+
module ClassMethods
|
5
|
+
attr_reader :natural_key_fields
|
6
|
+
|
7
|
+
def natural_key(*fields)
|
8
|
+
@natural_key_fields = fields.dup
|
9
|
+
validates_uniqueness_of_natural_key
|
10
|
+
end
|
11
|
+
|
12
|
+
def validates_uniqueness_of_natural_key
|
13
|
+
first, *rest = *natural_key_fields
|
14
|
+
if rest.empty?
|
15
|
+
validates_uniqueness_of first
|
16
|
+
else
|
17
|
+
validates_uniqueness_of first, :scope => rest
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module InstanceMethods
|
23
|
+
def natural_key_hash
|
24
|
+
{}.tap do |hash|
|
25
|
+
self.class.natural_key_fields.each do |field|
|
26
|
+
hash[field] = self.send(field)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.included(receiver)
|
33
|
+
receiver.extend ClassMethods
|
34
|
+
receiver.send :include, InstanceMethods
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "tilt"
|
2
|
+
|
3
|
+
module Stratify
|
4
|
+
module Renderable
|
5
|
+
def self.included(base)
|
6
|
+
base.extend ClassMethods
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def template(data = nil)
|
11
|
+
@template = data unless data.nil?
|
12
|
+
@template
|
13
|
+
end
|
14
|
+
|
15
|
+
def template_format(format = nil)
|
16
|
+
@template_format = format unless format.nil?
|
17
|
+
@template_format || default_template_format
|
18
|
+
end
|
19
|
+
|
20
|
+
def default_template_format
|
21
|
+
:erb
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_html
|
26
|
+
template_handler = Tilt[self.class.template_format].new { self.class.template.strip }
|
27
|
+
template_handler.render(presenter)
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the object that will be passed to the template for rendering.
|
31
|
+
#
|
32
|
+
# The default implementation returns 'self' (i.e., the renderable object).
|
33
|
+
#
|
34
|
+
# Subclasses may optionally override this method to provide an object
|
35
|
+
# better suited for use in rendering (e.g., an object implementing the
|
36
|
+
# presenter pattern).
|
37
|
+
def presenter
|
38
|
+
self
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/spec/mongoid.yml
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
# This file defines an example Stratify collector and activity for testing
|
2
|
+
# purposes.
|
3
|
+
#
|
4
|
+
# Stratify::Bacon::Activity and Stratify::Bacon::Collector represent a
|
5
|
+
# (fictitious, unfortunately) service for tracking your bacon-related
|
6
|
+
# achievements. This also happens to be an *amazing* idea for a service.
|
7
|
+
# You know you want to track your bacon-related achievements. You just know it.
|
8
|
+
|
9
|
+
# Stratify::Bacon::Activity implements all *mandatory* functionality required
|
10
|
+
# for it to be a valid activity.
|
11
|
+
module Stratify
|
12
|
+
module Bacon
|
13
|
+
class Activity < Stratify::Activity
|
14
|
+
field :slices, :type => Integer
|
15
|
+
|
16
|
+
natural_key :created_at
|
17
|
+
|
18
|
+
template "Enjoyed <%= slices %> slices of delicious bacon"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Stratify::Bacon::Collector implements all *mandatory* functionality required
|
24
|
+
# for it to be a valid collector.
|
25
|
+
module Stratify
|
26
|
+
module Bacon
|
27
|
+
class Collector < Stratify::Collector
|
28
|
+
source "Baconation"
|
29
|
+
|
30
|
+
configuration_fields :username => {:type => :string},
|
31
|
+
:password => {:type => :password}
|
32
|
+
|
33
|
+
# Return a fixed set of Stratify::Bacon::Activity objects. (A real
|
34
|
+
# collector would tend to return new data as time goes by. For testing
|
35
|
+
# purposes, it's convenient to have a fixed set of data returned by the
|
36
|
+
# collector.)
|
37
|
+
def activities
|
38
|
+
[
|
39
|
+
Stratify::Bacon::Activity.new(:slices => 3, :created_at => Time.new(2011, 4, 3, 7, 2)),
|
40
|
+
Stratify::Bacon::Activity.new(:slices => 5, :created_at => Time.new(2011, 4, 7, 8, 17)),
|
41
|
+
Stratify::Bacon::Activity.new(:slices => 4, :created_at => Time.new(2011, 4, 9, 6, 24)),
|
42
|
+
]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
require 'rspec'
|
4
|
+
require 'stratify-base'
|
5
|
+
|
6
|
+
# Requires supporting files with custom matchers and macros, etc,
|
7
|
+
# in ./support/ and its subdirectories.
|
8
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
9
|
+
|
10
|
+
require 'database_cleaner'
|
11
|
+
|
12
|
+
require 'prototypes/bacon'
|
13
|
+
|
14
|
+
RSpec.configure do |config|
|
15
|
+
config.color_enabled = true
|
16
|
+
config.formatter = :progress
|
17
|
+
config.mock_with :mocha
|
18
|
+
|
19
|
+
# Configure RSpec to run focused specs, and also respect the alias 'fit' for focused specs
|
20
|
+
config.filter_run :focused => true
|
21
|
+
config.run_all_when_everything_filtered = true
|
22
|
+
config.alias_example_to :fit, :focused => true
|
23
|
+
|
24
|
+
# Configure RSpec to truncate the database before any spec tagged with ":database => true"
|
25
|
+
DatabaseCleaner.strategy = :truncation
|
26
|
+
DatabaseCleaner.orm = "mongoid"
|
27
|
+
config.before(:each, :database => true) do
|
28
|
+
DatabaseCleaner.clean
|
29
|
+
end
|
30
|
+
|
31
|
+
config.before(:suite) do
|
32
|
+
silence_mongoid_logging
|
33
|
+
initialize_mongoid_configuration
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def silence_mongoid_logging
|
38
|
+
Mongoid.logger = Logger.new("/dev/null")
|
39
|
+
end
|
40
|
+
|
41
|
+
def silence_stratify_logging
|
42
|
+
Stratify.stubs(:logger).returns(Logger.new("/dev/null")) # Silence the logger so as not to clutter the test output
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize_mongoid_configuration
|
46
|
+
mongoid_config = YAML::load_file(File.join(File.dirname(__FILE__), "mongoid.yml"))
|
47
|
+
Mongoid.from_hash(mongoid_config)
|
48
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stratify::Activity do
|
4
|
+
|
5
|
+
describe "#created_on" do
|
6
|
+
it "returns the date portion of the created_at value" do
|
7
|
+
activity = Stratify::Activity.new(:created_at => DateTime.parse("2010-11-27 6:35 PM"))
|
8
|
+
activity.created_on.should == Date.parse("2010-11-27")
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns nil if the created_at value is nil" do
|
12
|
+
activity = Stratify::Activity.new(:created_at => nil)
|
13
|
+
activity.created_on.should be_nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#delete", :database => true do
|
18
|
+
it "soft-deletes the activity" do
|
19
|
+
creation_time = Time.now
|
20
|
+
activity = Stratify::Bacon::Activity.create!(:slices => 42, :created_at => creation_time)
|
21
|
+
activity.delete
|
22
|
+
|
23
|
+
Stratify::Bacon::Activity.where(:slices => 42, :created_at => creation_time).should_not exist
|
24
|
+
Stratify::Bacon::Activity.deleted.where(:slices => 42, :created_at => creation_time).should exist
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#duplicate?", :database => true do
|
29
|
+
class ActivityForTestingDuplicates < Stratify::Activity
|
30
|
+
field :foo
|
31
|
+
field :bar
|
32
|
+
|
33
|
+
natural_key :foo, :bar
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns false if no record exists with the same natural key" do
|
37
|
+
ActivityForTestingDuplicates.create!(:foo => "a", :bar => "b", :created_at => Time.now)
|
38
|
+
ActivityForTestingDuplicates.new(:foo => "1", :bar => "2").should_not be_duplicate
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns true if a saved record already exists with the same natural key" do
|
42
|
+
ActivityForTestingDuplicates.create!(:foo => "a", :bar => "b", :created_at => Time.now)
|
43
|
+
ActivityForTestingDuplicates.new(:foo => "a", :bar => "b").should be_duplicate
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns true if a soft-deleted record already exists with the same natural key" do
|
47
|
+
original = ActivityForTestingDuplicates.new(:foo => "a", :bar => "b", :created_at => Time.now)
|
48
|
+
original.save!
|
49
|
+
original.delete
|
50
|
+
|
51
|
+
ActivityForTestingDuplicates.new(:foo => "a", :bar => "b").should be_duplicate
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stratify::Archiver do
|
4
|
+
|
5
|
+
describe ".run" do
|
6
|
+
context "when the collection succeeds" do
|
7
|
+
it "updates the last_ran_at timestamp for the collector" do
|
8
|
+
stub_current_timestamp = Time.parse "2011-04-30 14:11:02"
|
9
|
+
Time.stubs(:now).returns stub_current_timestamp
|
10
|
+
|
11
|
+
collector = Stratify::Collector.create
|
12
|
+
archiver = Stratify::Archiver.new(collector)
|
13
|
+
archiver.stubs(:collect_activities)
|
14
|
+
archiver.run
|
15
|
+
collector.last_ran_at.should == stub_current_timestamp
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context "when an exception occurs during collection" do
|
20
|
+
it "propagates the exception to the caller" do
|
21
|
+
archiver = Stratify::Archiver.new(collector = stub)
|
22
|
+
archiver.stubs(:collect_activities).raises("some gnarly error")
|
23
|
+
lambda { archiver.run }.should raise_error
|
24
|
+
end
|
25
|
+
|
26
|
+
it "updates the last_ran_at timestamp for the collector" do
|
27
|
+
stub_current_timestamp = Time.parse "2011-04-30 14:11:02"
|
28
|
+
Time.stubs(:now).returns stub_current_timestamp
|
29
|
+
|
30
|
+
collector = Stratify::Collector.create
|
31
|
+
archiver = Stratify::Archiver.new(collector)
|
32
|
+
archiver.stubs(:collect_activities).raises("some gnarly error")
|
33
|
+
archiver.run rescue nil
|
34
|
+
collector.last_ran_at.should == stub_current_timestamp
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe ".collect_activities" do
|
40
|
+
it "documents the source of each activity" do
|
41
|
+
example_collector_class = Class.new(Stratify::Collector)
|
42
|
+
example_collector_class.source("some-example-source")
|
43
|
+
collector = example_collector_class.new
|
44
|
+
|
45
|
+
activity = Stratify::Activity.new
|
46
|
+
collector.stubs(:activities).returns [activity]
|
47
|
+
|
48
|
+
archiver = Stratify::Archiver.new(collector)
|
49
|
+
archiver.stubs(:persist_activity)
|
50
|
+
archiver.send(:collect_activities)
|
51
|
+
activity.source.should == "some-example-source"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "persists each activity" do
|
55
|
+
collector = Stratify::Collector.new
|
56
|
+
activity = Stratify::Activity.new
|
57
|
+
collector.stubs(:activities).returns [activity]
|
58
|
+
|
59
|
+
archiver = Stratify::Archiver.new(collector)
|
60
|
+
archiver.expects(:persist_activity).with(activity)
|
61
|
+
archiver.send(:collect_activities)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "persisting activities" do
|
66
|
+
it "logs when an error is encountered attempting to persist an activity" do
|
67
|
+
activity = stub('activity', :duplicate? => false, :save => false, :errors => {})
|
68
|
+
|
69
|
+
archiver = Stratify::Archiver.new(collector = stub)
|
70
|
+
|
71
|
+
Stratify.logger.expects(:error).with() { |value| value.starts_with? "Failed to persist activity" }
|
72
|
+
archiver.send(:persist_activity, activity)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "does not log an error when activity is persisted successfully" do
|
76
|
+
activity = stub('activity', :duplicate? => false, :save => true)
|
77
|
+
|
78
|
+
archiver = Stratify::Archiver.new(collector = stub)
|
79
|
+
|
80
|
+
Stratify.logger.expects(:error).never
|
81
|
+
archiver.send(:persist_activity, activity)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stratify::CollectorCoordinator do
|
4
|
+
|
5
|
+
describe ".run_all" do
|
6
|
+
it "runs all collectors" do
|
7
|
+
collector_1 = mock(:run)
|
8
|
+
collector_2 = mock(:run)
|
9
|
+
|
10
|
+
Stratify::Collector.stubs(:all).returns([collector_1, collector_2])
|
11
|
+
|
12
|
+
Stratify::CollectorCoordinator.run_all
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when an exception occurs in a collector" do
|
16
|
+
it "logs the exception" do
|
17
|
+
collector = stub
|
18
|
+
collector.stubs(:run).raises("some gnarly error")
|
19
|
+
Stratify::Collector.stubs(:all).returns([collector])
|
20
|
+
|
21
|
+
Stratify.logger.expects(:error).with() { |value| value.include? "some gnarly error" }
|
22
|
+
Stratify::CollectorCoordinator.run_all
|
23
|
+
end
|
24
|
+
|
25
|
+
it "runs the remaining collectors" do
|
26
|
+
silence_stratify_logging # Silence the logger so as not to clutter the test output
|
27
|
+
|
28
|
+
troublesome_collector = stub
|
29
|
+
troublesome_collector.stubs(:run).raises("some gnarly error")
|
30
|
+
|
31
|
+
other_collector = mock
|
32
|
+
other_collector.expects(:run).returns(nil)
|
33
|
+
|
34
|
+
Stratify::Collector.stubs(:all).returns([troublesome_collector, other_collector])
|
35
|
+
|
36
|
+
Stratify::CollectorCoordinator.run_all
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class TestCollector < Stratify::Collector
|
4
|
+
configuration_fields :username => {:type => :string},
|
5
|
+
:password => {:type => :password}
|
6
|
+
end
|
7
|
+
|
8
|
+
def anonymous_collector_subclass
|
9
|
+
Class.new(Stratify::Collector)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe Stratify::Collector do
|
13
|
+
|
14
|
+
describe ".collector_class_for" do
|
15
|
+
it "returns the collector subclass associated with the given source" do
|
16
|
+
example_collector_subclass = anonymous_collector_subclass
|
17
|
+
example_collector_subclass.source("Twitter")
|
18
|
+
Stratify::Collector.collector_class_for("Twitter").should == example_collector_subclass
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns nil when no collector subclass exists for the given source" do
|
22
|
+
Stratify::Collector.collector_class_for("lol").should be_nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".sources" do
|
27
|
+
before { Stratify::Collector.collector_classes.clear }
|
28
|
+
|
29
|
+
it "returns the list of sources for all collectors" do
|
30
|
+
anonymous_collector_subclass.source("FourSquare")
|
31
|
+
anonymous_collector_subclass.source("Twitter")
|
32
|
+
Stratify::Collector.sources.should =~ ["FourSquare", "Twitter"]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns the sources in case-insensitive alphabetical order" do
|
36
|
+
anonymous_collector_subclass.source("Twitter")
|
37
|
+
anonymous_collector_subclass.source("iTunes")
|
38
|
+
anonymous_collector_subclass.source("Instapaper")
|
39
|
+
anonymous_collector_subclass.source("Pandora")
|
40
|
+
Stratify::Collector.sources.should == %w(Instapaper iTunes Pandora Twitter)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe ".configuration_fields" do
|
45
|
+
it "tracks the fields used to configure the collector" do
|
46
|
+
fields = TestCollector.configuration_fields
|
47
|
+
fields.find {|f| f.name == :username && f.type == :string}.should be
|
48
|
+
fields.find {|f| f.name == :password && f.type == :password}.should be
|
49
|
+
end
|
50
|
+
|
51
|
+
it "registers the given fields with Mongoid" do
|
52
|
+
TestCollector.fields.should include("username", "password")
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "influences validation" do
|
56
|
+
it "adds an error when a collector instance fails to provide a value for each field" do
|
57
|
+
collector = TestCollector.new
|
58
|
+
collector.should_not be_valid
|
59
|
+
collector.errors[:username].should include("can't be blank")
|
60
|
+
end
|
61
|
+
|
62
|
+
it "adds NO errors when a collector instance provides a value for each field" do
|
63
|
+
collector = TestCollector.new(:username => "foo")
|
64
|
+
collector.valid?
|
65
|
+
collector.errors[:username].should_not include("can't be blank")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe ".configuration_instructions (class method)" do
|
71
|
+
it "returns the configuration instructions for a specific Collector subclass" do
|
72
|
+
collector_subclass = anonymous_collector_subclass
|
73
|
+
collector_subclass.configuration_instructions("Provide your username and ...")
|
74
|
+
collector_subclass.configuration_instructions.should == "Provide your username and ..."
|
75
|
+
end
|
76
|
+
|
77
|
+
it "returns nil if a Collector subclass does not specify any configuration instructions" do
|
78
|
+
anonymous_collector_subclass.configuration_instructions.should == nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe "#configuration_instructions (instance method)" do
|
83
|
+
it "returns the configuration instructions defined in the class" do
|
84
|
+
collector_subclass = anonymous_collector_subclass
|
85
|
+
collector_subclass.configuration_instructions("Provide your username and ...")
|
86
|
+
collector = collector_subclass.new
|
87
|
+
collector.configuration_instructions.should == "Provide your username and ..."
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#configuration_summary" do
|
92
|
+
context "when the collector's class has one configuration field" do
|
93
|
+
it "returns the value of the field" do
|
94
|
+
collector_subclass = Class.new(Stratify::Collector) do
|
95
|
+
configuration_fields :username => {:type => :string}
|
96
|
+
end
|
97
|
+
collector = collector_subclass.new
|
98
|
+
collector.username = "johndoe"
|
99
|
+
collector.configuration_summary.should == "johndoe"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "when the collector's class has multiple configuration fields" do
|
104
|
+
it "returns the value of the first field" do
|
105
|
+
collector_subclass = Class.new(Stratify::Collector) do
|
106
|
+
configuration_fields :username => {:type => :string},
|
107
|
+
:tag => {:type => :string}
|
108
|
+
end
|
109
|
+
collector = collector_subclass.new
|
110
|
+
collector.username = "johndoe"
|
111
|
+
collector.tag = "programming"
|
112
|
+
collector.configuration_summary.should == "johndoe"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when the collector's class has no configuration fields" do
|
117
|
+
it "returns nil" do
|
118
|
+
collector_subclass = Class.new(Stratify::Collector)
|
119
|
+
collector = collector_subclass.new
|
120
|
+
collector.configuration_summary.should == nil
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Stratify::FieldDefinition do
|
4
|
+
describe "#name" do
|
5
|
+
it "returns the name of the field" do
|
6
|
+
field = Stratify::FieldDefinition.new(:username, :type => :string)
|
7
|
+
field.name.should == :username
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#type" do
|
12
|
+
it "returns the type of the field" do
|
13
|
+
field = Stratify::FieldDefinition.new(:username, :type => :string)
|
14
|
+
field.type.should == :string
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#label" do
|
19
|
+
it "returns the label for the field when an explicit label is specified" do
|
20
|
+
field = Stratify::FieldDefinition.new(:username, :type => :string, :label => "User ID")
|
21
|
+
field.label.should == "User ID"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns the titleized name for the field when no explicit label is specified" do
|
25
|
+
field = Stratify::FieldDefinition.new(:username, :type => :string)
|
26
|
+
field.label.should == "Username"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "collecting activities", :database => true do
|
4
|
+
it "runs the collector and stores activities" do
|
5
|
+
collector = Stratify::Bacon::Collector.create!(:username => "johndoe", :password => "secret")
|
6
|
+
|
7
|
+
expect { collector.run }.to change(Stratify::Bacon::Activity, :count).by(3)
|
8
|
+
|
9
|
+
Stratify::Bacon::Activity.where(:slices => 3, :created_at => Time.new(2011, 4, 3, 7, 2)).should exist
|
10
|
+
Stratify::Bacon::Activity.where(:slices => 5, :created_at => Time.new(2011, 4, 7, 8, 17)).should exist
|
11
|
+
Stratify::Bacon::Activity.where(:slices => 4, :created_at => Time.new(2011, 4, 9, 6, 24)).should exist
|
12
|
+
end
|
13
|
+
|
14
|
+
it "does not import duplicate activities" do
|
15
|
+
collector = Stratify::Bacon::Collector.new(:username => "johndoe", :password => "secret")
|
16
|
+
expect { collector.run }.to change(Stratify::Bacon::Activity, :count).by(3)
|
17
|
+
expect { collector.run }.to change(Stratify::Bacon::Activity, :count).by(0)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "does not re-import soft-deleted activities" do
|
21
|
+
collector = Stratify::Bacon::Collector.new(:username => "johndoe", :password => "secret")
|
22
|
+
|
23
|
+
collector.run
|
24
|
+
activity = Stratify::Bacon::Activity.where(:created_at => Time.new(2011, 4, 3, 7, 2)).first
|
25
|
+
activity.should be
|
26
|
+
activity.delete
|
27
|
+
|
28
|
+
collector.run
|
29
|
+
Stratify::Bacon::Activity.where(:created_at => Time.new(2011, 4, 3, 7, 2)).should_not exist
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def class_with_natural_key_mixin(&blk)
|
4
|
+
Class.new do
|
5
|
+
include Mongoid::Document
|
6
|
+
include Stratify::MongoidExtension::NaturalKey
|
7
|
+
yield(self) if block_given?
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe Stratify::MongoidExtension::NaturalKey do
|
12
|
+
describe ".natural_key" do
|
13
|
+
context "given a single field as the key" do
|
14
|
+
it "stores the field in an array of key fields" do
|
15
|
+
klass = class_with_natural_key_mixin do |k|
|
16
|
+
k.natural_key :status_id
|
17
|
+
end
|
18
|
+
klass.natural_key_fields.should == [:status_id]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "given a multi-field key" do
|
23
|
+
it "stores the fields in an array of key fields" do
|
24
|
+
klass = class_with_natural_key_mixin do |k|
|
25
|
+
k.natural_key :url, :created_at
|
26
|
+
end
|
27
|
+
klass.natural_key_fields.should == [:url, :created_at]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it "declares a uniqueness validator for the natural key" do
|
32
|
+
klass = class_with_natural_key_mixin
|
33
|
+
klass.expects(:validates_uniqueness_of_natural_key)
|
34
|
+
klass.natural_key :foo
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".validates_uniqueness_of_natural_key" do
|
39
|
+
context "given a single field as the key" do
|
40
|
+
it "declares that no two documents can have the same value for that field" do
|
41
|
+
klass = class_with_natural_key_mixin
|
42
|
+
klass.stubs(:natural_key_fields).returns [:status_id]
|
43
|
+
klass.expects(:validates_uniqueness_of).with(:status_id)
|
44
|
+
klass.validates_uniqueness_of_natural_key
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "given a two-field key" do
|
49
|
+
it "declares that no two documents can have the same combination of values for these two fields" do
|
50
|
+
klass = class_with_natural_key_mixin
|
51
|
+
klass.stubs(:natural_key_fields).returns [:url, :created_at]
|
52
|
+
klass.expects(:validates_uniqueness_of).with(:url, :scope => [:created_at])
|
53
|
+
klass.validates_uniqueness_of_natural_key
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context "given a key with more than two fields" do
|
58
|
+
it "declares that no two documents can have the same combination of values for these fields" do
|
59
|
+
klass = class_with_natural_key_mixin
|
60
|
+
klass.stubs(:natural_key_fields).returns [:foo, :bar, :baz]
|
61
|
+
klass.expects(:validates_uniqueness_of).with(:foo, :scope => [:bar, :baz])
|
62
|
+
klass.validates_uniqueness_of_natural_key
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#natural_key_hash" do
|
68
|
+
it "returns the field name and value for the object's natural key" do
|
69
|
+
klass = class_with_natural_key_mixin do |k|
|
70
|
+
k.field :foo
|
71
|
+
k.field :bar
|
72
|
+
k.field :baz
|
73
|
+
k.natural_key :foo, :bar
|
74
|
+
end
|
75
|
+
|
76
|
+
model = klass.new(:foo => 1, :bar => 2, :baz => 3)
|
77
|
+
model.natural_key_hash.should == {:foo => 1, :bar => 2}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
def anonymous_class_with_renderable_mixin
|
4
|
+
Class.new do
|
5
|
+
include Stratify::Renderable
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
describe Stratify::Renderable do
|
10
|
+
describe ".template" do
|
11
|
+
it "returns the template specified for use in rendering the object" do
|
12
|
+
renderable_class = anonymous_class_with_renderable_mixin
|
13
|
+
renderable_class.template "some custom template"
|
14
|
+
renderable_class.template.should == "some custom template"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ".template_format" do
|
19
|
+
it "returns ':erb' when no explicit format has been set" do
|
20
|
+
renderable_class = anonymous_class_with_renderable_mixin
|
21
|
+
renderable_class.template_format.should == :erb
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns a custom template format when one has been set" do
|
25
|
+
renderable_class = anonymous_class_with_renderable_mixin
|
26
|
+
renderable_class.template_format :haml
|
27
|
+
renderable_class.template_format.should == :haml
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#presenter" do
|
32
|
+
it "returns the object" do
|
33
|
+
renderable_object = anonymous_class_with_renderable_mixin.new
|
34
|
+
renderable_object.presenter.should == renderable_object
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#to_html" do
|
39
|
+
it "returns the result of rendering the template with the presenter" do
|
40
|
+
renderable_class = anonymous_class_with_renderable_mixin
|
41
|
+
renderable_class.template "Hello, <%= name %>"
|
42
|
+
|
43
|
+
renderable_object = renderable_class.new
|
44
|
+
class << renderable_object
|
45
|
+
def name
|
46
|
+
"Kilgore"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
renderable_object.to_html.should == "Hello, Kilgore"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "stratify/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "stratify-base"
|
7
|
+
s.version = Stratify::Base::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Jason Rudolph"]
|
10
|
+
s.email = ["jason@jasonrudolph.com"]
|
11
|
+
s.homepage = "http://github.com/jasonrudolph/stratify/"
|
12
|
+
s.summary = "Core collector and activity componentry for Stratify"
|
13
|
+
s.description = "Provides the infrastructure to support the development and use of Stratify collectors and activities"
|
14
|
+
|
15
|
+
s.rubyforge_project = "stratify-base"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_runtime_dependency "bson_ext", "~> 1.3.1"
|
23
|
+
s.add_runtime_dependency "mongoid", "~> 2.0.2"
|
24
|
+
s.add_runtime_dependency "tilt", "~> 1.3.2"
|
25
|
+
|
26
|
+
s.add_development_dependency "rspec", "~> 2.6.0"
|
27
|
+
s.add_development_dependency "mocha", "~> 0.9.12"
|
28
|
+
s.add_development_dependency "database_cleaner", "~> 0.6.7"
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: stratify-base
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jason Rudolph
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-06-26 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: bson_ext
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.3.1
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: mongoid
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.0.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: tilt
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 1.3.2
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rspec
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 2.6.0
|
57
|
+
type: :development
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: mocha
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ~>
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 0.9.12
|
68
|
+
type: :development
|
69
|
+
version_requirements: *id005
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: database_cleaner
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ~>
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: 0.6.7
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id006
|
81
|
+
description: Provides the infrastructure to support the development and use of Stratify collectors and activities
|
82
|
+
email:
|
83
|
+
- jason@jasonrudolph.com
|
84
|
+
executables: []
|
85
|
+
|
86
|
+
extensions: []
|
87
|
+
|
88
|
+
extra_rdoc_files: []
|
89
|
+
|
90
|
+
files:
|
91
|
+
- .gitignore
|
92
|
+
- .rvmrc
|
93
|
+
- Gemfile
|
94
|
+
- Gemfile.lock
|
95
|
+
- LICENSE
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- lib/stratify-base.rb
|
99
|
+
- lib/stratify/activity.rb
|
100
|
+
- lib/stratify/archiver.rb
|
101
|
+
- lib/stratify/collector.rb
|
102
|
+
- lib/stratify/collector_coordinator.rb
|
103
|
+
- lib/stratify/field_definition.rb
|
104
|
+
- lib/stratify/logger.rb
|
105
|
+
- lib/stratify/mongoid_extension.rb
|
106
|
+
- lib/stratify/renderable.rb
|
107
|
+
- lib/stratify/version.rb
|
108
|
+
- spec/mongoid.yml
|
109
|
+
- spec/prototypes/bacon.rb
|
110
|
+
- spec/spec_helper.rb
|
111
|
+
- spec/stratify/activity_spec.rb
|
112
|
+
- spec/stratify/archiver_spec.rb
|
113
|
+
- spec/stratify/collector_coordinator_spec.rb
|
114
|
+
- spec/stratify/collector_spec.rb
|
115
|
+
- spec/stratify/field_definition_spec.rb
|
116
|
+
- spec/stratify/integration_spec.rb
|
117
|
+
- spec/stratify/mongoid_extension_spec.rb
|
118
|
+
- spec/stratify/renderable_spec.rb
|
119
|
+
- stratify-base.gemspec
|
120
|
+
homepage: http://github.com/jasonrudolph/stratify/
|
121
|
+
licenses: []
|
122
|
+
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: "0"
|
134
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
|
+
none: false
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: "0"
|
140
|
+
requirements: []
|
141
|
+
|
142
|
+
rubyforge_project: stratify-base
|
143
|
+
rubygems_version: 1.8.5
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Core collector and activity componentry for Stratify
|
147
|
+
test_files:
|
148
|
+
- spec/mongoid.yml
|
149
|
+
- spec/prototypes/bacon.rb
|
150
|
+
- spec/spec_helper.rb
|
151
|
+
- spec/stratify/activity_spec.rb
|
152
|
+
- spec/stratify/archiver_spec.rb
|
153
|
+
- spec/stratify/collector_coordinator_spec.rb
|
154
|
+
- spec/stratify/collector_spec.rb
|
155
|
+
- spec/stratify/field_definition_spec.rb
|
156
|
+
- spec/stratify/integration_spec.rb
|
157
|
+
- spec/stratify/mongoid_extension_spec.rb
|
158
|
+
- spec/stratify/renderable_spec.rb
|