mordor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ pkg/*
2
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1 @@
1
+ gemspec
data/README ADDED
@@ -0,0 +1,13 @@
1
+ Small library to add DataMapper style resources for MongoDB.
2
+
3
+ class ExampleResource
4
+ include Mordor::Resource
5
+
6
+ attribute :first
7
+ attribute :second
8
+ attribute :third, :finder_method => :find_by_third_attribute
9
+ end
10
+
11
+ This adds attr_accessors to the ExampleResource for each attribute, plus adds finder methods of the form
12
+ find_by_{attribute}. The naming convention can be overridden by using the optional :finder_method option,
13
+ as can be seen with the third attribute.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ load('tasks/github-gem.rake')
2
+
3
+ # Register the gem release tasks in the gem namespace
4
+ GithubGem::RakeTasks.new(:gem) do |config|
5
+
6
+ # Note that the following values are all default values and can
7
+ # therefore be omitted if they are not changed.
8
+
9
+ config.gemspec_file = GithubGem.detect_gemspec_file
10
+ config.main_include = GithubGem.detect_main_include
11
+ config.root_dir = Dir.pwd
12
+ config.test_pattern = 'test/**/*_test.rb'
13
+ config.spec_pattern = 'spec/**/*_spec.rb'
14
+ config.local_branch = 'master'
15
+ config.remote = 'origin'
16
+ config.remote_branch = 'master'
17
+ end
data/lib/mordor.rb ADDED
@@ -0,0 +1,97 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+ require 'extlib'
4
+ require 'mordor/version'
5
+ require 'mordor/collection'
6
+ require 'mordor/resource'
7
+
8
+ unless Object.const_defined?('BigDecimal')
9
+ BigDecimal = Float
10
+ end
11
+
12
+ class Date
13
+ def to_time(form = :utc)
14
+ Time.send("#{form}", year, month, day)
15
+ end
16
+
17
+ def to_gm
18
+ Time.gm(year, month, day).to_datetime
19
+ end
20
+
21
+ def to_local
22
+ Time.local(year, month, day).to_datetime
23
+ end
24
+
25
+ def to_datetime
26
+ DateTime.civil(self.year, self.mon, self.day)
27
+ end
28
+
29
+ def show(format = nil)
30
+ case format
31
+ when :human
32
+ strftime("%d-%m-%Y")
33
+ else
34
+ to_s
35
+ end
36
+ end
37
+
38
+ def full_string
39
+ strftime("%A %d %B %Y")
40
+ end
41
+ end
42
+
43
+ class DateTime
44
+ def to_datetime
45
+ self
46
+ end
47
+
48
+ def to_date
49
+ Date.civil(self.year, self.mon, self.day)
50
+ end
51
+
52
+ def show(format = nil)
53
+ case format
54
+ when :human
55
+ strftime("%d-%m-%Y %H:%M")
56
+ when :full
57
+ strftime("%d-%m-%Y %H:%M:%S")
58
+ else
59
+ to_s
60
+ end
61
+ end
62
+ end
63
+
64
+ class Time
65
+
66
+ def to_date
67
+ Date.civil(year, month, day)
68
+ end if RUBY_VERSION < '1.8.6'
69
+
70
+ def show(format = nil)
71
+ return self.to_date.show(format) if [hour,min] == [0,0]
72
+ case format
73
+ when :human
74
+ strftime("%d-%m-%Y %H:%m")
75
+ when :full
76
+ strftime("%d-%m-%Y %H:%M:%S")
77
+ else
78
+ to_s
79
+ end
80
+ end
81
+ end
82
+
83
+ module Mordor
84
+ CONFIG = {
85
+ :hostname => 'localhost',
86
+ :port => 27017,
87
+ :database => 'development'
88
+ }
89
+
90
+ def connection
91
+ @connection ||= Mongo::Connection.new(CONFIG[:hostname], CONFIG[:port])
92
+ @connection.autenticate(CONFIG[:username], CONFIG[:password]) if CONFIG[:username]
93
+ @connection.db(CONFIG[:database])
94
+ end
95
+ module_function :connection
96
+
97
+ end
@@ -0,0 +1,38 @@
1
+ module Mordor
2
+ class Collection
3
+ include Enumerable
4
+
5
+ def initialize(klass, cursor)
6
+ @klass = klass
7
+ @cursor = cursor
8
+ end
9
+
10
+ def each
11
+ @cursor.each do |element|
12
+ if element
13
+ yield @klass.new(element)
14
+ else
15
+ next
16
+ end
17
+ end
18
+ end
19
+
20
+ def first
21
+ result = @cursor.first
22
+ @cursor.rewind!
23
+ result ? @klass.new(result) : nil
24
+ end
25
+
26
+ def size
27
+ @cursor.count
28
+ end
29
+
30
+ def method_missing(method, *args, &block)
31
+ if @cursor.respond_to?(method)
32
+ self.class.new(@klass, @cursor.__send__(method, *args, &block))
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,136 @@
1
+ module Mordor
2
+ module Resource
3
+ attr_accessor :_id
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ def initialize(attributes = {})
10
+ attributes.each do |k,v|
11
+ self.send("#{k}=", v)
12
+ end
13
+ end
14
+
15
+ def replace_params(params = {})
16
+ result = {}
17
+ return result unless params
18
+ params.each do |key, value|
19
+ value = replace_type(value)
20
+ key = key.to_s.gsub(/\W|\./, "_")
21
+ result[key] = value
22
+ end
23
+ result
24
+ end
25
+
26
+ def replace_type(value)
27
+ case value
28
+ when Hash
29
+ value = replace_params(value)
30
+ when Date, DateTime
31
+ value = value.to_time
32
+ when BigDecimal
33
+ value = value.to_f
34
+ when Array
35
+ value = value.map do |val|
36
+ replace_type(val)
37
+ end
38
+ when Integer
39
+ else
40
+ value = value.to_s
41
+ end
42
+ value
43
+ end
44
+
45
+ def save
46
+ unless self._id
47
+ insert_id = self.class.collection.insert(self.to_hash)
48
+ self._id = insert_id
49
+ else
50
+ insert_id = self.update
51
+ end
52
+ insert_id != nil
53
+ end
54
+
55
+ def update
56
+ insert_id = self.class.collection.update({:_id => self._id}, self.to_hash)
57
+ insert_id
58
+ end
59
+
60
+ def collection
61
+ self.class.collection
62
+ end
63
+
64
+ def to_hash
65
+ attributes = self.class.instance_variable_get(:@attributes)
66
+ result = {}
67
+ return result unless attributes
68
+ attributes.each do |attribute_name|
69
+ result[attribute_name] = replace_type(self.send(attribute_name))
70
+ end
71
+ result
72
+ end
73
+
74
+ module ClassMethods
75
+ def collection
76
+ connection.collection(self.collection_name)
77
+ end
78
+
79
+ def collection_name
80
+ klassname = self.to_s.downcase.gsub(/[\/|.|::]/, '_')
81
+ "#{klassname}s"
82
+ end
83
+
84
+ def get(id)
85
+ if id.is_a?(String)
86
+ id = BSON::ObjectId.from_string(id)
87
+ end
88
+ if attributes = collection.find_one(:_id => id)
89
+ new(attributes)
90
+ else
91
+ nil
92
+ end
93
+ end
94
+
95
+ def connection
96
+ @connection ||= Mordor.connection
97
+ end
98
+
99
+ def find_by_id(id)
100
+ get(id)
101
+ end
102
+
103
+ def find_by_day(day)
104
+ case day
105
+ when DateTime
106
+ start = day.to_date.to_time
107
+ end_of_day = (day.to_date + 1).to_time
108
+ when Date
109
+ start = day.to_time
110
+ end_of_day = (day + 1).to_time
111
+ when Time
112
+ start = day.to_datetime.to_date.to_time
113
+ end_of_day = (day.to_date + 1).to_datetime.to_date.to_time
114
+ end
115
+ cursor = collection.find(:at => {'$gte' => start, '$lt' => end_of_day})
116
+ Collection.new(self, cursor)
117
+ end
118
+
119
+ def attribute(name, options = {})
120
+ @attributes ||= []
121
+ @attributes << name unless @attributes.include?(name)
122
+
123
+ method_name = options.key?(:finder_method) ? options[:finder_method] : "find_by_#{name}"
124
+
125
+
126
+ class_eval <<-EOS, __FILE__, __LINE__
127
+ attr_accessor name
128
+
129
+ def self.#{method_name}(value)
130
+ Collection.new(self, collection.find(:#{name} => value))
131
+ end
132
+ EOS
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,3 @@
1
+ module Mordor
2
+ VERSION = "0.0.1"
3
+ end
data/mordor.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "mordor"
3
+
4
+ # Do not set the version and date field manually, this is done by the release script
5
+ s.version = "0.1.0"
6
+ s.date = "2011-11-08"
7
+
8
+ s.summary = "mordor"
9
+ s.description = <<-eos
10
+ Small gem to add MongoDB Resources, resources have attributes that translate into document fields. When an attribute is declared, finders for the attribute are added to the Resource automatically
11
+ eos
12
+
13
+ s.add_development_dependency('rake')
14
+ s.add_development_dependency('ruby-debug')
15
+ s.add_development_dependency('rspec', '~> 2.0')
16
+
17
+ s.add_development_dependency('extlib')
18
+ s.add_development_dependency('mongo')
19
+ s.add_development_dependency('bson_ext')
20
+
21
+ s.add_runtime_dependency('extlib')
22
+ s.add_runtime_dependency('mongo')
23
+ s.add_runtime_dependency('bson_ext')
24
+
25
+ s.authors = ['Jan-Willem Koelewijn', 'Dirkjan Bussink']
26
+ s.email = ['janwillem.koelewijn@nedap.com', 'dirkjan.bussink@nedap.com']
27
+ s.homepage = 'http://www.nedap.com'
28
+
29
+ # The files and test_files directives are set automatically by the release script.
30
+ # Do not change them by hand, but make sure to add the files to the git repository.
31
+ s.files = %w(.gitignore Gemfile README Rakefile lib/mordor.rb lib/mordor/collection.rb lib/mordor/resource.rb lib/mordor/version.rb mordor.gemspec spec/mordor/connection_spec.rb spec/mordor/resource_spec.rb spec/spec.opts spec/spec_helper.rb tasks/github-gem.rake)
32
+ end
33
+
@@ -0,0 +1,16 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
2
+
3
+ describe "connecting to mongo" do
4
+
5
+ before :each do
6
+ clean_sheet
7
+ end
8
+
9
+ it "should have a connection to mongo" do
10
+ @connection.should be_instance_of(Mongo::Connection)
11
+ end
12
+
13
+ it "should select the correct database" do
14
+ @db.name.should == Mordor::CONFIG[:database]
15
+ end
16
+ end
@@ -0,0 +1,140 @@
1
+ require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
2
+
3
+ describe "with respect to resources" do
4
+ class TestResource
5
+ include Mordor::Resource
6
+
7
+ attribute :first
8
+ attribute :second
9
+ attribute :third, :finder_method => :find_by_third_attribute
10
+ end
11
+
12
+ it "should create accessor methods for all attributes" do
13
+ ["first", "first=", "second", "second="].each{ |v| TestResource.public_instance_methods.should include(v) }
14
+ end
15
+
16
+ it "should create class level finder methods for all attributes" do
17
+ ["find_by_first", "find_by_second"].each do |finder_method|
18
+ TestResource.methods.should include(finder_method)
19
+ end
20
+ end
21
+
22
+ it "should create finder methods with the supplied finder method name" do
23
+ TestResource.methods.should include "find_by_third_attribute"
24
+ end
25
+
26
+ context "with respect to replacing params" do
27
+ before :each do
28
+ clean_sheet
29
+ end
30
+
31
+ it "should correctly substitute non-alphanumeric characters in keys with underscores" do
32
+ options = {
33
+ "o*p#t>i_o@n)s" => "test"
34
+ }
35
+ result = TestResource.new.replace_params(options)
36
+ result.keys.first.should eql "o_p_t_i_o_n_s"
37
+ end
38
+
39
+ it "should correctly replace Date and DateTimes" do
40
+ options = {
41
+ "option" => Date.today,
42
+ "another" => DateTime.now
43
+ }
44
+ result = TestResource.new.replace_params(options)
45
+ result.each do |k, v|
46
+ v.should be_a Time
47
+ end
48
+ end
49
+
50
+ it "should correctly replace BigDecimals" do
51
+ options = {
52
+ "option" => BigDecimal.new("1.00")
53
+ }
54
+ result = TestResource.new.replace_params(options)
55
+ result.each do |k,v|
56
+ v.should be_a Float
57
+ end
58
+ end
59
+
60
+ it "should correctly respond to to_hash" do
61
+ resource = TestResource.new({:first => "first", :second => "second", :third => "third"})
62
+ hash = resource.to_hash
63
+ hash.size.should == 3
64
+ hash[:first].should == "first"
65
+ hash[:second].should == "second"
66
+ hash[:third].should == "third"
67
+ end
68
+ end
69
+
70
+ context "with respect to saving and retrieving" do
71
+ before :each do
72
+ clean_sheet
73
+ end
74
+
75
+ it "should correctly save resources" do
76
+ resource = TestResource.new({:first => "first", :second => "second"})
77
+ resource.save.should be_true
78
+ resource._id.should_not be_nil
79
+ resource.collection.count.should == 1
80
+ resource.collection.find_one['_id'].should == resource._id
81
+ end
82
+
83
+ it "should correctly update resources" do
84
+ resource = TestResource.new({:first => "first", :second => "second"})
85
+ resource.save.should be_true
86
+ resource._id.should_not be_nil
87
+
88
+ original_id = resource._id
89
+
90
+ resource.collection.count.should == 1
91
+ resource.collection.find_one['_id'].should == resource._id
92
+
93
+ resource.first = "third"
94
+ resource.save.should be_true
95
+ resource._id.should == original_id
96
+ resource.collection.find_one['first'].should == resource.first
97
+ end
98
+
99
+ it "should be able to find resources by their ids" do
100
+ resource = TestResource.new({:first => "first", :second => "second"})
101
+ resource.save.should be_true
102
+ res = TestResource.find_by_id(resource._id)
103
+ res._id.should == resource._id
104
+ res.first.should == resource.first
105
+ res.second.should == resource.second
106
+ end
107
+
108
+ it "should be able to find resources by their ids as strings" do
109
+ resource = TestResource.new({:first => "first", :second => "second"})
110
+ resource.save.should be_true
111
+ res = TestResource.find_by_id(resource._id.to_s)
112
+ res._id.should == resource._id
113
+ res.first.should == resource.first
114
+ res.second.should == resource.second
115
+ end
116
+ end
117
+
118
+ context "with respect to collections" do
119
+ it "should correctly return a collection name" do
120
+ TestResource.collection_name.should == "testresources"
121
+ end
122
+
123
+ it "should correctly create a connection" do
124
+ TestResource.connection.should_not be_nil
125
+ end
126
+ end
127
+
128
+ context "with respect to not finding something" do
129
+ it "should just return an empty collection when a collection query doesn't return results" do
130
+ col = TestResource.find_by_day(DateTime.civil(2011, 11, 8))
131
+ col.size.should == 0
132
+ end
133
+
134
+ it "should return nil when an non existing id is queried" do
135
+ clean_sheet
136
+ resource = TestResource.find_by_id('4eb8f3570e02e10cce000002')
137
+ resource.should be_nil
138
+ end
139
+ end
140
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,2 @@
1
+ --format specdoc
2
+ --colour
@@ -0,0 +1,22 @@
1
+ require 'rubygems'
2
+ require 'mongo'
3
+
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+ require 'mordor'
6
+
7
+ module Auditing
8
+ CONFIG = {
9
+ :hostname => 'localhost',
10
+ :port => 27017,
11
+ :database => 'test'
12
+ }
13
+ end
14
+
15
+ def clean_sheet
16
+ @connection ||= Mongo::Connection.new(Mordor::CONFIG[:hostname], Mordor::CONFIG[:port])
17
+ @db ||= @connection[Mordor::CONFIG[:database]]
18
+ if Object.const_defined?('TestResource')
19
+ @db[TestResource.collection_name].drop
20
+ end
21
+ end
22
+
@@ -0,0 +1,368 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/tasklib'
4
+ require 'date'
5
+ require 'set'
6
+
7
+ module GithubGem
8
+
9
+ # Detects the gemspc file of this project using heuristics.
10
+ def self.detect_gemspec_file
11
+ FileList['*.gemspec'].first
12
+ end
13
+
14
+ # Detects the main include file of this project using heuristics
15
+ def self.detect_main_include
16
+ if File.exist?(File.expand_path("../lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb", detect_gemspec_file))
17
+ "lib/#{File.basename(detect_gemspec_file, '.gemspec').gsub(/-/, '/')}.rb"
18
+ elsif FileList['lib/*.rb'].length == 1
19
+ FileList['lib/*.rb'].first
20
+ else
21
+ nil
22
+ end
23
+ end
24
+
25
+ class RakeTasks
26
+
27
+ include Rake::DSL if Rake.const_defined?('DSL')
28
+
29
+ attr_reader :gemspec, :modified_files
30
+ attr_accessor :gemspec_file, :task_namespace, :main_include, :root_dir, :spec_pattern, :test_pattern, :remote, :remote_branch, :local_branch
31
+
32
+ # Initializes the settings, yields itself for configuration
33
+ # and defines the rake tasks based on the gemspec file.
34
+ def initialize(task_namespace = :gem)
35
+ @gemspec_file = GithubGem.detect_gemspec_file
36
+ @task_namespace = task_namespace
37
+ @main_include = GithubGem.detect_main_include
38
+ @modified_files = Set.new
39
+ @root_dir = Dir.pwd
40
+ @test_pattern = 'test/**/*_test.rb'
41
+ @spec_pattern = 'spec/**/*_spec.rb'
42
+ @local_branch = 'master'
43
+ @remote = 'origin'
44
+ @remote_branch = 'master'
45
+
46
+ yield(self) if block_given?
47
+
48
+ load_gemspec!
49
+ define_tasks!
50
+ end
51
+
52
+ protected
53
+
54
+ def git
55
+ @git ||= ENV['GIT'] || 'git'
56
+ end
57
+
58
+ # Define Unit test tasks
59
+ def define_test_tasks!
60
+ require 'rake/testtask'
61
+
62
+ namespace(:test) do
63
+ Rake::TestTask.new(:basic) do |t|
64
+ t.pattern = test_pattern
65
+ t.verbose = true
66
+ t.libs << 'test'
67
+ end
68
+ end
69
+
70
+ desc "Run all unit tests for #{gemspec.name}"
71
+ task(:test => ['test:basic'])
72
+ end
73
+
74
+ # Defines RSpec tasks
75
+ def define_rspec_tasks!
76
+ require 'rspec/core/rake_task'
77
+
78
+ namespace(:spec) do
79
+ desc "Verify all RSpec examples for #{gemspec.name}"
80
+ RSpec::Core::RakeTask.new(:basic) do |t|
81
+ t.pattern = spec_pattern
82
+ end
83
+
84
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
85
+ RSpec::Core::RakeTask.new(:specdoc) do |t|
86
+ t.pattern = spec_pattern
87
+ t.rspec_opts = ['--format', 'documentation', '--color']
88
+ end
89
+
90
+ desc "Run RCov on specs for #{gemspec.name}"
91
+ RSpec::Core::RakeTask.new(:rcov) do |t|
92
+ t.pattern = spec_pattern
93
+ t.rcov = true
94
+ t.rcov_opts = ['--exclude', '"spec/*,gems/*"', '--rails']
95
+ end
96
+ end
97
+
98
+ desc "Verify all RSpec examples for #{gemspec.name} and output specdoc"
99
+ task(:spec => ['spec:specdoc'])
100
+ end
101
+
102
+ # Defines the rake tasks
103
+ def define_tasks!
104
+
105
+ define_test_tasks! if has_tests?
106
+ define_rspec_tasks! if has_specs?
107
+
108
+ namespace(@task_namespace) do
109
+ desc "Updates the filelist in the gemspec file"
110
+ task(:manifest) { manifest_task }
111
+
112
+ desc "Builds the .gem package"
113
+ task(:build => :manifest) { build_task }
114
+
115
+ desc "Sets the version of the gem in the gemspec"
116
+ task(:set_version => [:check_version, :check_current_branch]) { version_task }
117
+ task(:check_version => :fetch_origin) { check_version_task }
118
+
119
+ task(:fetch_origin) { fetch_origin_task }
120
+ task(:check_current_branch) { check_current_branch_task }
121
+ task(:check_clean_status) { check_clean_status_task }
122
+ task(:check_not_diverged => :fetch_origin) { check_not_diverged_task }
123
+
124
+ #checks = [:check_current_branch, :check_clean_status, :check_not_diverged, :check_version]
125
+ checks = [:check_current_branch, :check_clean_status]
126
+ checks.unshift('spec:basic') if has_specs?
127
+ checks.unshift('test:basic') if has_tests?
128
+ # checks.push << [:check_rubyforge] if gemspec.rubyforge_project
129
+
130
+ desc "Perform all checks that would occur before a release"
131
+ task(:release_checks => checks)
132
+
133
+ release_tasks = [:release_checks, :set_version, :build, :github_release, :gemcutter_release]
134
+ # release_tasks << [:rubyforge_release] if gemspec.rubyforge_project
135
+
136
+ desc "Release a new version of the gem using the VERSION environment variable"
137
+ task(:release => release_tasks) { release_task }
138
+
139
+ namespace(:release) do
140
+ desc "Release the next version of the gem, by incrementing the last version segment by 1"
141
+ task(:next => [:next_version] + release_tasks) { release_task }
142
+
143
+ desc "Release the next version of the gem, using a patch increment (0.0.1)"
144
+ task(:patch => [:next_patch_version] + release_tasks) { release_task }
145
+
146
+ desc "Release the next version of the gem, using a minor increment (0.1.0)"
147
+ task(:minor => [:next_minor_version] + release_tasks) { release_task }
148
+
149
+ desc "Release the next version of the gem, using a major increment (1.0.0)"
150
+ task(:major => [:next_major_version] + release_tasks) { release_task }
151
+ end
152
+
153
+ # task(:check_rubyforge) { check_rubyforge_task }
154
+ # task(:rubyforge_release) { rubyforge_release_task }
155
+ task(:gemcutter_release) { gemcutter_release_task }
156
+ task(:github_release => [:commit_modified_files, :tag_version]) { github_release_task }
157
+ task(:tag_version) { tag_version_task }
158
+ task(:commit_modified_files) { commit_modified_files_task }
159
+
160
+ task(:next_version) { next_version_task }
161
+ task(:next_patch_version) { next_version_task(:patch) }
162
+ task(:next_minor_version) { next_version_task(:minor) }
163
+ task(:next_major_version) { next_version_task(:major) }
164
+
165
+ desc "Updates the gem release tasks with the latest version on Github"
166
+ task(:update_tasks) { update_tasks_task }
167
+ end
168
+ end
169
+
170
+ # Updates the files list and test_files list in the gemspec file using the list of files
171
+ # in the repository and the spec/test file pattern.
172
+ def manifest_task
173
+ # Load all the gem's files using "git ls-files"
174
+ repository_files = `#{git} ls-files`.split("\n")
175
+ test_files = Dir[test_pattern] + Dir[spec_pattern]
176
+
177
+ update_gemspec(:files, repository_files)
178
+ update_gemspec(:test_files, repository_files & test_files)
179
+ end
180
+
181
+ # Builds the gem
182
+ def build_task
183
+ sh "gem build -q #{gemspec_file}"
184
+ Dir.mkdir('pkg') unless File.exist?('pkg')
185
+ sh "mv #{gemspec.name}-#{gemspec.version}.gem pkg/#{gemspec.name}-#{gemspec.version}.gem"
186
+ end
187
+
188
+ def newest_version
189
+ `#{git} tag`.split("\n").map { |tag| tag.split('-').last }.compact.map { |v| Gem::Version.new(v) }.max || Gem::Version.new('0.0.0')
190
+ end
191
+
192
+ def next_version(increment = nil)
193
+ next_version = newest_version.segments
194
+ increment_index = case increment
195
+ when :micro then 3
196
+ when :patch then 2
197
+ when :minor then 1
198
+ when :major then 0
199
+ else next_version.length - 1
200
+ end
201
+
202
+ next_version[increment_index] ||= 0
203
+ next_version[increment_index] = next_version[increment_index].succ
204
+ ((increment_index + 1)...next_version.length).each { |i| next_version[i] = 0 }
205
+
206
+ Gem::Version.new(next_version.join('.'))
207
+ end
208
+
209
+ def next_version_task(increment = nil)
210
+ ENV['VERSION'] = next_version(increment).version
211
+ puts "Releasing version #{ENV['VERSION']}..."
212
+ end
213
+
214
+ # Updates the version number in the gemspec file, the VERSION constant in the main
215
+ # include file and the contents of the VERSION file.
216
+ def version_task
217
+ update_gemspec(:version, ENV['VERSION']) if ENV['VERSION']
218
+ update_gemspec(:date, Date.today)
219
+
220
+ update_version_file(gemspec.version)
221
+ update_version_constant(gemspec.version)
222
+ end
223
+
224
+ def check_version_task
225
+ raise "#{ENV['VERSION']} is not a valid version number!" if ENV['VERSION'] && !Gem::Version.correct?(ENV['VERSION'])
226
+ proposed_version = Gem::Version.new((ENV['VERSION'] || gemspec.version).dup)
227
+ raise "This version (#{proposed_version}) is not higher than the highest tagged version (#{newest_version})" if newest_version >= proposed_version
228
+ end
229
+
230
+ # Checks whether the current branch is not diverged from the remote branch
231
+ def check_not_diverged_task
232
+ raise "The current branch is diverged from the remote branch!" if `#{git} rev-list HEAD..#{remote}/#{remote_branch}`.split("\n").any?
233
+ end
234
+
235
+ # Checks whether the repository status ic clean
236
+ def check_clean_status_task
237
+ raise "The current working copy contains modifications" if `#{git} ls-files -m`.split("\n").any?
238
+ end
239
+
240
+ # Checks whether the current branch is correct
241
+ def check_current_branch_task
242
+ raise "Currently not on #{local_branch} branch!" unless `#{git} branch`.split("\n").detect { |b| /^\* / =~ b } == "* #{local_branch}"
243
+ end
244
+
245
+ # Fetches the latest updates from Github
246
+ def fetch_origin_task
247
+ sh git, 'fetch', remote
248
+ end
249
+
250
+ # Commits every file that has been changed by the release task.
251
+ def commit_modified_files_task
252
+ really_modified = `#{git} ls-files -m #{modified_files.entries.join(' ')}`.split("\n")
253
+ if really_modified.any?
254
+ really_modified.each { |file| sh git, 'add', file }
255
+ sh git, 'commit', '-m', "Released #{gemspec.name} gem version #{gemspec.version}."
256
+ end
257
+ end
258
+
259
+ # Adds a tag for the released version
260
+ def tag_version_task
261
+ sh git, 'tag', '-a', "#{gemspec.name}-#{gemspec.version}", '-m', "Released #{gemspec.name} gem version #{gemspec.version}."
262
+ end
263
+
264
+ # Pushes the changes and tag to github
265
+ def github_release_task
266
+ sh git, 'push', '--tags', remote, remote_branch
267
+ end
268
+
269
+ def gemcutter_release_task
270
+ sh "gem", 'push', "pkg/#{gemspec.name}-#{gemspec.version}.gem"
271
+ end
272
+
273
+ # Gem release task.
274
+ # All work is done by the task's dependencies, so just display a release completed message.
275
+ def release_task
276
+ puts
277
+ puts "Release successful."
278
+ end
279
+
280
+ private
281
+
282
+ # Checks whether this project has any RSpec files
283
+ def has_specs?
284
+ FileList[spec_pattern].any?
285
+ end
286
+
287
+ # Checks whether this project has any unit test files
288
+ def has_tests?
289
+ FileList[test_pattern].any?
290
+ end
291
+
292
+ # Loads the gemspec file
293
+ def load_gemspec!
294
+ @gemspec = eval(File.read(@gemspec_file))
295
+ end
296
+
297
+ # Updates the VERSION file with the new version
298
+ def update_version_file(version)
299
+ if File.exists?('VERSION')
300
+ File.open('VERSION', 'w') { |f| f << version.to_s }
301
+ modified_files << 'VERSION'
302
+ end
303
+ end
304
+
305
+ # Updates the VERSION constant in the main include file if it exists
306
+ def update_version_constant(version)
307
+ if main_include && File.exist?(main_include)
308
+ file_contents = File.read(main_include)
309
+ if file_contents.sub!(/^(\s+VERSION\s*=\s*)[^\s].*$/) { $1 + version.to_s.inspect }
310
+ File.open(main_include, 'w') { |f| f << file_contents }
311
+ modified_files << main_include
312
+ end
313
+ end
314
+ end
315
+
316
+ # Updates an attribute of the gemspec file.
317
+ # This function will open the file, and search/replace the attribute using a regular expression.
318
+ def update_gemspec(attribute, new_value, literal = false)
319
+
320
+ unless literal
321
+ new_value = case new_value
322
+ when Array then "%w(#{new_value.join(' ')})"
323
+ when Hash, String then new_value.inspect
324
+ when Date then new_value.strftime('%Y-%m-%d').inspect
325
+ else raise "Cannot write value #{new_value.inspect} to gemspec file!"
326
+ end
327
+ end
328
+
329
+ spec = File.read(gemspec_file)
330
+ regexp = Regexp.new('^(\s+\w+\.' + Regexp.quote(attribute.to_s) + '\s*=\s*)[^\s].*$')
331
+ if spec.sub!(regexp) { $1 + new_value }
332
+ File.open(gemspec_file, 'w') { |f| f << spec }
333
+ modified_files << gemspec_file
334
+
335
+ # Reload the gemspec so the changes are incorporated
336
+ load_gemspec!
337
+
338
+ # Also mark the Gemfile.lock file as changed because of the new version.
339
+ modified_files << 'Gemfile.lock' if File.exist?(File.join(root_dir, 'Gemfile.lock'))
340
+ end
341
+ end
342
+
343
+ # Updates the tasks file using the latest file found on Github
344
+ def update_tasks_task
345
+ require 'net/https'
346
+ require 'uri'
347
+
348
+ uri = URI.parse('https://raw.github.com/wvanbergen/github-gem/master/tasks/github-gem.rake')
349
+ http = Net::HTTP.new(uri.host, uri.port)
350
+ http.use_ssl = true
351
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
352
+ response = http.request(Net::HTTP::Get.new(uri.path))
353
+
354
+ if Net::HTTPSuccess === response
355
+ open(__FILE__, "w") { |file| file.write(response.body) }
356
+ relative_file = File.expand_path(__FILE__).sub(%r[^#{@root_dir}/], '')
357
+ if `#{git} ls-files -m #{relative_file}`.split("\n").any?
358
+ sh git, 'add', relative_file
359
+ sh git, 'commit', '-m', "Updated to latest gem release management tasks."
360
+ else
361
+ puts "Release managament tasks already are at the latest version."
362
+ end
363
+ else
364
+ raise "Download failed with HTTP status #{response.code}!"
365
+ end
366
+ end
367
+ end
368
+ end
metadata ADDED
@@ -0,0 +1,209 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mordor
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Jan-Willem Koelewijn
14
+ - Dirkjan Bussink
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-11-08 00:00:00 +01:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: rake
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :development
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: ruby-debug
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :development
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rspec
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ hash: 3
59
+ segments:
60
+ - 2
61
+ - 0
62
+ version: "2.0"
63
+ type: :development
64
+ version_requirements: *id003
65
+ - !ruby/object:Gem::Dependency
66
+ name: extlib
67
+ prerelease: false
68
+ requirement: &id004 !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :development
78
+ version_requirements: *id004
79
+ - !ruby/object:Gem::Dependency
80
+ name: mongo
81
+ prerelease: false
82
+ requirement: &id005 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ type: :development
92
+ version_requirements: *id005
93
+ - !ruby/object:Gem::Dependency
94
+ name: bson_ext
95
+ prerelease: false
96
+ requirement: &id006 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ hash: 3
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ type: :development
106
+ version_requirements: *id006
107
+ - !ruby/object:Gem::Dependency
108
+ name: extlib
109
+ prerelease: false
110
+ requirement: &id007 !ruby/object:Gem::Requirement
111
+ none: false
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ hash: 3
116
+ segments:
117
+ - 0
118
+ version: "0"
119
+ type: :runtime
120
+ version_requirements: *id007
121
+ - !ruby/object:Gem::Dependency
122
+ name: mongo
123
+ prerelease: false
124
+ requirement: &id008 !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ hash: 3
130
+ segments:
131
+ - 0
132
+ version: "0"
133
+ type: :runtime
134
+ version_requirements: *id008
135
+ - !ruby/object:Gem::Dependency
136
+ name: bson_ext
137
+ prerelease: false
138
+ requirement: &id009 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ">="
142
+ - !ruby/object:Gem::Version
143
+ hash: 3
144
+ segments:
145
+ - 0
146
+ version: "0"
147
+ type: :runtime
148
+ version_requirements: *id009
149
+ description: " Small gem to add MongoDB Resources, resources have attributes that translate into document fields. When an attribute is declared, finders for the attribute are added to the Resource automatically\n"
150
+ email:
151
+ - janwillem.koelewijn@nedap.com
152
+ - dirkjan.bussink@nedap.com
153
+ executables: []
154
+
155
+ extensions: []
156
+
157
+ extra_rdoc_files: []
158
+
159
+ files:
160
+ - .gitignore
161
+ - Gemfile
162
+ - README
163
+ - Rakefile
164
+ - lib/mordor.rb
165
+ - lib/mordor/collection.rb
166
+ - lib/mordor/resource.rb
167
+ - lib/mordor/version.rb
168
+ - mordor.gemspec
169
+ - spec/mordor/connection_spec.rb
170
+ - spec/mordor/resource_spec.rb
171
+ - spec/spec.opts
172
+ - spec/spec_helper.rb
173
+ - tasks/github-gem.rake
174
+ has_rdoc: true
175
+ homepage: http://www.nedap.com
176
+ licenses: []
177
+
178
+ post_install_message:
179
+ rdoc_options: []
180
+
181
+ require_paths:
182
+ - lib
183
+ required_ruby_version: !ruby/object:Gem::Requirement
184
+ none: false
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ hash: 3
189
+ segments:
190
+ - 0
191
+ version: "0"
192
+ required_rubygems_version: !ruby/object:Gem::Requirement
193
+ none: false
194
+ requirements:
195
+ - - ">="
196
+ - !ruby/object:Gem::Version
197
+ hash: 3
198
+ segments:
199
+ - 0
200
+ version: "0"
201
+ requirements: []
202
+
203
+ rubyforge_project:
204
+ rubygems_version: 1.3.7
205
+ signing_key:
206
+ specification_version: 3
207
+ summary: mordor
208
+ test_files: []
209
+