qcourses 0.1.8 → 0.1.9
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/.autotest +2 -2
- data/.rspec +0 -1
- data/Gemfile.lock +27 -5
- data/lib/factories.rb +22 -14
- data/lib/qcourses.rb +1 -0
- data/lib/qcourses/controllers/base.rb +20 -1
- data/lib/qcourses/controllers/events_controller.rb +6 -7
- data/lib/qcourses/controllers/registrations_controller.rb +4 -1
- data/lib/qcourses/models.rb +1 -1
- data/lib/qcourses/models/event.rb +12 -0
- data/lib/qcourses/models/postman.rb +50 -0
- data/lib/qcourses/qcourses.rake.rb +0 -1
- data/lib/qcourses/version.rb +1 -1
- data/lib/qcourses/view_helpers.rb +2 -2
- data/qcourses.gemspec +4 -1
- data/spec/factories_spec.rb +45 -12
- data/spec/qcourses/controllers/courses_controller_spec.rb +2 -2
- data/spec/qcourses/controllers/events_controller_spec.rb +16 -10
- data/spec/qcourses/controllers/registrations_controller_spec.rb +8 -1
- data/spec/qcourses/models/course_repository_spec.rb +1 -0
- data/spec/qcourses/models/event_spec.rb +20 -3
- data/spec/qcourses/models/postman_spec.rb +62 -0
- data/spec/qcourses/models/registration_spec.rb +6 -0
- data/spec/qcourses/view_helpers_spec.rb +12 -6
- data/spec/spec_helper.rb +6 -0
- data/spec/support/factories.rb +17 -15
- metadata +54 -4
data/.autotest
CHANGED
data/.rspec
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
qcourses (0.1.
|
|
4
|
+
qcourses (0.1.8)
|
|
5
5
|
haml (~> 3.1.4)
|
|
6
|
+
pony (~> 1.4)
|
|
6
7
|
sequel (~> 3.33.0)
|
|
7
|
-
sinatra (~> 1.
|
|
8
|
+
sinatra (~> 1.3)
|
|
8
9
|
sqlite3 (~> 1.3.5)
|
|
9
10
|
|
|
10
11
|
GEM
|
|
@@ -22,14 +23,27 @@ GEM
|
|
|
22
23
|
childprocess (0.3.2)
|
|
23
24
|
ffi (~> 1.0.6)
|
|
24
25
|
diff-lcs (1.1.3)
|
|
26
|
+
email_spec (1.2.1)
|
|
27
|
+
mail (~> 2.2)
|
|
28
|
+
rspec (~> 2.0)
|
|
25
29
|
ffi (1.0.11)
|
|
26
30
|
haml (3.1.4)
|
|
31
|
+
i18n (0.6.0)
|
|
27
32
|
libwebsocket (0.1.3)
|
|
28
33
|
addressable
|
|
34
|
+
mail (2.4.4)
|
|
35
|
+
i18n (>= 0.4.0)
|
|
36
|
+
mime-types (~> 1.16)
|
|
37
|
+
treetop (~> 1.4.8)
|
|
29
38
|
mime-types (1.18)
|
|
30
39
|
multi_json (1.3.2)
|
|
31
40
|
nokogiri (1.5.2)
|
|
41
|
+
polyglot (0.3.3)
|
|
42
|
+
pony (1.4)
|
|
43
|
+
mail (> 2.0)
|
|
32
44
|
rack (1.4.1)
|
|
45
|
+
rack-protection (1.2.0)
|
|
46
|
+
rack
|
|
33
47
|
rack-test (0.6.1)
|
|
34
48
|
rack (>= 1.0)
|
|
35
49
|
rspec (2.9.0)
|
|
@@ -48,11 +62,17 @@ GEM
|
|
|
48
62
|
multi_json (~> 1.0)
|
|
49
63
|
rubyzip
|
|
50
64
|
sequel (3.33.0)
|
|
51
|
-
|
|
52
|
-
rack (
|
|
53
|
-
|
|
65
|
+
shotgun (0.9)
|
|
66
|
+
rack (>= 1.0)
|
|
67
|
+
sinatra (1.3.2)
|
|
68
|
+
rack (~> 1.3, >= 1.3.6)
|
|
69
|
+
rack-protection (~> 1.2)
|
|
70
|
+
tilt (~> 1.3, >= 1.3.3)
|
|
54
71
|
sqlite3 (1.3.6)
|
|
55
72
|
tilt (1.3.3)
|
|
73
|
+
treetop (1.4.10)
|
|
74
|
+
polyglot
|
|
75
|
+
polyglot (>= 0.3.1)
|
|
56
76
|
xpath (0.1.4)
|
|
57
77
|
nokogiri (~> 1.3)
|
|
58
78
|
|
|
@@ -62,6 +82,8 @@ PLATFORMS
|
|
|
62
82
|
DEPENDENCIES
|
|
63
83
|
ZenTest
|
|
64
84
|
capybara
|
|
85
|
+
email_spec
|
|
65
86
|
qcourses!
|
|
66
87
|
rack-test
|
|
67
88
|
rspec (~> 2.8)
|
|
89
|
+
shotgun
|
data/lib/factories.rb
CHANGED
|
@@ -2,14 +2,14 @@ module Rubory
|
|
|
2
2
|
def self.define(name, &definition)
|
|
3
3
|
factories.define(name, &definition)
|
|
4
4
|
end
|
|
5
|
-
def self.create(name)
|
|
5
|
+
def self.create(name, attribute_overrides = {})
|
|
6
6
|
factories.create(name)
|
|
7
7
|
end
|
|
8
|
-
def self.build(name)
|
|
9
|
-
factories.build(name)
|
|
8
|
+
def self.build(name, attribute_overrides = {})
|
|
9
|
+
factories.build(name, attribute_overrides)
|
|
10
10
|
end
|
|
11
|
-
def self.attributes_for(name)
|
|
12
|
-
factories.attributes_for(name)
|
|
11
|
+
def self.attributes_for(name, attribute_overrides = {})
|
|
12
|
+
factories.attributes_for(name, attribute_overrides)
|
|
13
13
|
end
|
|
14
14
|
def self.use_default_module(default_module)
|
|
15
15
|
factories.use_default_module(default_module)
|
|
@@ -31,16 +31,16 @@ module Rubory
|
|
|
31
31
|
def define(name, &definition)
|
|
32
32
|
factories[name] = CreationDsl.create_factory(name, self, &definition)
|
|
33
33
|
end
|
|
34
|
-
def create(name)
|
|
35
|
-
object = build(name)
|
|
34
|
+
def create(name, attribute_overrides = {})
|
|
35
|
+
object = build(name, attribute_overrides)
|
|
36
36
|
object.save
|
|
37
37
|
object
|
|
38
38
|
end
|
|
39
|
-
def build(name)
|
|
40
|
-
factory(name).build
|
|
39
|
+
def build(name, attribute_overrides={})
|
|
40
|
+
factory(name).build(attribute_overrides)
|
|
41
41
|
end
|
|
42
|
-
def attributes_for(name)
|
|
43
|
-
object = build(name)
|
|
42
|
+
def attributes_for(name, attribute_overrides = {})
|
|
43
|
+
object = build(name, attribute_overrides)
|
|
44
44
|
object.values || object.attributes || raise(NotSupportedException.new(":attributes_for is not supported as your model does not support :values or :attributes methods"))
|
|
45
45
|
end
|
|
46
46
|
def factory(name)
|
|
@@ -68,7 +68,7 @@ module Rubory
|
|
|
68
68
|
end
|
|
69
69
|
def self.create_factory(name,context, &definition)
|
|
70
70
|
f = Factory.new(name, context)
|
|
71
|
-
new(f,context)
|
|
71
|
+
definition.call(new(f,context))
|
|
72
72
|
return f
|
|
73
73
|
end
|
|
74
74
|
def method_missing(method, *args, &creation_block)
|
|
@@ -92,8 +92,8 @@ module Rubory
|
|
|
92
92
|
def value_for(attribute, &block)
|
|
93
93
|
@attributes[attribute] = block;
|
|
94
94
|
end
|
|
95
|
-
def build
|
|
96
|
-
@context.create_instance class_name, Hash[
|
|
95
|
+
def build(attribute_overrides)
|
|
96
|
+
@context.create_instance class_name, Hash[ attributes(attribute_overrides) ]
|
|
97
97
|
end
|
|
98
98
|
private
|
|
99
99
|
def count
|
|
@@ -105,6 +105,14 @@ module Rubory
|
|
|
105
105
|
def camelize(str)
|
|
106
106
|
str.to_s.split("_").map {|w| w.capitalize}.join
|
|
107
107
|
end
|
|
108
|
+
def attributes(attribute_overrides)
|
|
109
|
+
@attributes.merge(attribute_overrides).to_a.map do |attribute|
|
|
110
|
+
[attribute[0], attribute_value(attribute[1])]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
def attribute_value(value)
|
|
114
|
+
value.is_a?(Proc) ? value.call(count) : value
|
|
115
|
+
end
|
|
108
116
|
end
|
|
109
117
|
class NoSuchFactoryException < Exception; end
|
|
110
118
|
class NotSupportedException < Exception; end
|
data/lib/qcourses.rb
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
1
|
require 'sinatra/base'
|
|
2
|
+
require 'sinatra/showexceptions'
|
|
2
3
|
require 'qcourses/resource_paths'
|
|
3
4
|
require 'haml'
|
|
5
|
+
|
|
6
|
+
|
|
4
7
|
module Qcourses
|
|
5
|
-
class BaseController < Sinatra::
|
|
8
|
+
class BaseController < Sinatra::Base
|
|
6
9
|
include ResourcePaths
|
|
7
10
|
include Configuration
|
|
8
11
|
set :root, Proc.new { Qcourses.config.root }
|
|
9
12
|
set :public_folder, File.expand_path('../../../public/', File.dirname(__FILE__))
|
|
10
13
|
resource_admin_on '/admin'
|
|
11
14
|
|
|
15
|
+
configure :development do
|
|
16
|
+
use Rack::Logger, ::Logger::DEBUG
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
configure :production do
|
|
20
|
+
use Rack::Logger, ::Logger::INFO
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
configure :test do
|
|
24
|
+
disable :logging
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
before do
|
|
28
|
+
logger.info request.path
|
|
29
|
+
end
|
|
30
|
+
|
|
12
31
|
helpers do
|
|
13
32
|
include ViewHelpers
|
|
14
33
|
include Renderers
|
|
@@ -47,13 +47,12 @@ module Qcourses
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
put admin_request_url(:id) do
|
|
50
|
+
@event = Event.find(params[:id])
|
|
50
51
|
begin
|
|
51
|
-
@event
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
haml :'events/edit', layout: :admin
|
|
56
|
-
end
|
|
52
|
+
@event.update event_params
|
|
53
|
+
redirect admin_request_url
|
|
54
|
+
rescue ValidationFailed
|
|
55
|
+
haml :'events/edit', layout: :admin
|
|
57
56
|
rescue Exception => e
|
|
58
57
|
haml :'trainings/error', locals: { message: e.message }
|
|
59
58
|
end
|
|
@@ -65,7 +64,7 @@ module Qcourses
|
|
|
65
64
|
end
|
|
66
65
|
def filter_event_params
|
|
67
66
|
result = params[:event]
|
|
68
|
-
valid_parameters = ["course_id", "from", "to", "location"]
|
|
67
|
+
valid_parameters = ["course_id", "from", "to", "location", "max_participants"]
|
|
69
68
|
if (result[:location_id] && result[:location_id] != '0')
|
|
70
69
|
valid_parameters << "location_id"
|
|
71
70
|
valid_parameters.delete 'location'
|
|
@@ -18,14 +18,17 @@ module Qcourses
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
begin
|
|
21
|
+
registration = nil
|
|
21
22
|
Registration.db.transaction do
|
|
22
23
|
@company.save
|
|
23
24
|
@employees.each do |employee|
|
|
24
25
|
employee.company = @company
|
|
25
26
|
employee.save
|
|
26
|
-
Registration.create(event: @event, employee:employee)
|
|
27
|
+
registration = Registration.create(event: @event, employee:employee)
|
|
27
28
|
end
|
|
28
29
|
end
|
|
30
|
+
Postman.deliver_registration_notification(RegistrationNotification.new(@employees.first, @event))
|
|
31
|
+
Postman.deliver_registration_confirmation(@employees.first.email, RegistrationNotification.new(@employees.first, @event))
|
|
29
32
|
redirect "/registrations/success"
|
|
30
33
|
rescue Sequel::ValidationFailed
|
|
31
34
|
haml :'/registrations/new', layout: :registration
|
data/lib/qcourses/models.rb
CHANGED
|
@@ -3,7 +3,11 @@ module Qcourses
|
|
|
3
3
|
class Event < Sequel::Model
|
|
4
4
|
plugin :validation_helpers
|
|
5
5
|
many_to_one :location
|
|
6
|
+
one_to_many :registrations
|
|
6
7
|
|
|
8
|
+
def initialize(attributes = {})
|
|
9
|
+
super({:open => true}.merge attributes)
|
|
10
|
+
end
|
|
7
11
|
def self.opens(object_id)
|
|
8
12
|
first{ ({id => object_id}) & (from > Time.now) }
|
|
9
13
|
end
|
|
@@ -12,6 +16,10 @@ module Qcourses
|
|
|
12
16
|
order(:from).filter { from > Time.now }
|
|
13
17
|
end
|
|
14
18
|
|
|
19
|
+
def self.find(id)
|
|
20
|
+
self[id]
|
|
21
|
+
end
|
|
22
|
+
|
|
15
23
|
def validate
|
|
16
24
|
super
|
|
17
25
|
validates_presence :from
|
|
@@ -31,6 +39,10 @@ module Qcourses
|
|
|
31
39
|
course.name
|
|
32
40
|
end
|
|
33
41
|
|
|
42
|
+
def open?
|
|
43
|
+
max_participants > registrations.size
|
|
44
|
+
end
|
|
45
|
+
|
|
34
46
|
def subtitle
|
|
35
47
|
return '' unless course
|
|
36
48
|
course.subtitle
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require 'pony'
|
|
2
|
+
module Qcourses
|
|
3
|
+
|
|
4
|
+
class RegistrationNotification
|
|
5
|
+
def initialize(employee, event)
|
|
6
|
+
@employee = employee
|
|
7
|
+
@event = event
|
|
8
|
+
end
|
|
9
|
+
def event_name
|
|
10
|
+
@event.name
|
|
11
|
+
end
|
|
12
|
+
def inspect
|
|
13
|
+
"RegistrationNotification(for: #{employee.name}, about: #{event.name})"
|
|
14
|
+
end
|
|
15
|
+
def ==(other)
|
|
16
|
+
return false unless other.is_a? RegistrationNotification
|
|
17
|
+
return other.employee.email == employee.email && other.event == event
|
|
18
|
+
end
|
|
19
|
+
protected
|
|
20
|
+
attr_reader :employee, :event
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
class Postman
|
|
24
|
+
FROM_ADDRESS = "info@qwan.it"
|
|
25
|
+
NOTIFICATION_ADDRESS = "info@qwan.it"
|
|
26
|
+
@@allow_delivery_failure = false
|
|
27
|
+
def self.allow_delivery_failure
|
|
28
|
+
@@allow_delivery_failure = true
|
|
29
|
+
end
|
|
30
|
+
def self.dont_allow_delivery_failure
|
|
31
|
+
@@allow_delivery_failure = false
|
|
32
|
+
end
|
|
33
|
+
def self.deliver_registration_notification(registration_confirmation)
|
|
34
|
+
deliver(from: FROM_ADDRESS, to: NOTIFICATION_ADDRESS,
|
|
35
|
+
subject: "Course Registration for #{registration_confirmation.event_name}")
|
|
36
|
+
end
|
|
37
|
+
def self.deliver_registration_confirmation(addressee, registration_confirmation)
|
|
38
|
+
deliver(from: FROM_ADDRESS,
|
|
39
|
+
to: addressee,
|
|
40
|
+
subject: "Thank you for your registration for #{registration_confirmation.event_name}")
|
|
41
|
+
end
|
|
42
|
+
def self.deliver(options)
|
|
43
|
+
begin
|
|
44
|
+
Pony.mail(options)
|
|
45
|
+
rescue Exception => e
|
|
46
|
+
raise e unless @@allow_delivery_failure
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/qcourses/version.rb
CHANGED
|
@@ -4,7 +4,7 @@ module Qcourses
|
|
|
4
4
|
return '' unless options
|
|
5
5
|
options.collect do |option|
|
|
6
6
|
tag_attributes = {:value => option[0]}
|
|
7
|
-
tag_attributes[:selected] = "selected" if value == option[0]
|
|
7
|
+
tag_attributes[:selected] = "selected" if value.to_s == option[0].to_s
|
|
8
8
|
haml "%option#{tag_attributes.inspect} #{option[1]}", :layout => false
|
|
9
9
|
end.join
|
|
10
10
|
end
|
|
@@ -32,7 +32,7 @@ module Qcourses
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def event_registration_link(event)
|
|
35
|
-
return "closed" unless event.open
|
|
35
|
+
return "closed" unless event.open?
|
|
36
36
|
haml "%a{ :href=> url('/registrations/new/#{event.id}') } register"
|
|
37
37
|
end
|
|
38
38
|
|
data/qcourses.gemspec
CHANGED
|
@@ -20,13 +20,16 @@ Gem::Specification.new do |s|
|
|
|
20
20
|
|
|
21
21
|
# specify any dependencies here; for example:
|
|
22
22
|
# s.add_development_dependency "rspec"
|
|
23
|
-
s.add_runtime_dependency "sinatra", "~> 1.
|
|
23
|
+
s.add_runtime_dependency "sinatra", "~> 1.3"
|
|
24
24
|
s.add_runtime_dependency "haml", "~> 3.1.4"
|
|
25
25
|
s.add_runtime_dependency "sequel", "~> 3.33.0"
|
|
26
26
|
s.add_runtime_dependency "sqlite3", "~> 1.3.5"
|
|
27
|
+
s.add_runtime_dependency "pony", "~> 1.4"
|
|
27
28
|
|
|
28
29
|
s.add_development_dependency "rspec", "~> 2.8"
|
|
29
30
|
s.add_development_dependency "rack-test"
|
|
30
31
|
s.add_development_dependency "ZenTest"
|
|
31
32
|
s.add_development_dependency "capybara"
|
|
33
|
+
s.add_development_dependency "shotgun"
|
|
34
|
+
s.add_development_dependency "email_spec"
|
|
32
35
|
end
|
data/spec/factories_spec.rb
CHANGED
|
@@ -18,9 +18,9 @@ module Rubory
|
|
|
18
18
|
let(:factories) { Factories.new("Rubory") }
|
|
19
19
|
|
|
20
20
|
before do
|
|
21
|
-
factories.define(:person) do
|
|
22
|
-
name "name"
|
|
23
|
-
email { "email" }
|
|
21
|
+
factories.define(:person) do |f|
|
|
22
|
+
f.name "name"
|
|
23
|
+
f.email { "email" }
|
|
24
24
|
end
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -34,14 +34,26 @@ module Rubory
|
|
|
34
34
|
person = factories.build(:person)
|
|
35
35
|
person.email.should == 'email'
|
|
36
36
|
end
|
|
37
|
+
it "can override attributes" do
|
|
38
|
+
person = factories.build(:person, :name => "overridden name")
|
|
39
|
+
person.name.should == 'overridden name'
|
|
40
|
+
end
|
|
41
|
+
it "can override attributes with string key" do
|
|
42
|
+
person = factories.build(:person, "name" => "overridden name")
|
|
43
|
+
person.name.should == 'overridden name'
|
|
44
|
+
end
|
|
45
|
+
it "can specify an attribute missing in the factory definition" do
|
|
46
|
+
person = factories.build(:person, sirname: "sirname")
|
|
47
|
+
person.sirname.should == 'sirname'
|
|
48
|
+
end
|
|
37
49
|
it "throws no such factory if factory does not exist" do
|
|
38
50
|
expect { factories.build(:bogus) }.to raise_exception Rubory::NoSuchFactoryException
|
|
39
51
|
end
|
|
40
52
|
end
|
|
41
53
|
context "when attribute has n as block param" do
|
|
42
54
|
it "generates a unique object" do
|
|
43
|
-
factories.define(:person) do
|
|
44
|
-
name {|n| "name_#{n}" }
|
|
55
|
+
factories.define(:person) do |f|
|
|
56
|
+
f.name {|n| "name_#{n}" }
|
|
45
57
|
end
|
|
46
58
|
factories.build(:person).name.should == "name_1"
|
|
47
59
|
factories.build(:person).name.should == "name_2"
|
|
@@ -49,9 +61,9 @@ module Rubory
|
|
|
49
61
|
end
|
|
50
62
|
context "when an object has dependencies" do
|
|
51
63
|
before do
|
|
52
|
-
factories.define(:address) do
|
|
53
|
-
city "city"
|
|
54
|
-
associate :person
|
|
64
|
+
factories.define(:address) do |f|
|
|
65
|
+
f.city "city"
|
|
66
|
+
f.associate :person
|
|
55
67
|
end
|
|
56
68
|
end
|
|
57
69
|
let(:address) { factories.build :address }
|
|
@@ -64,6 +76,16 @@ module Rubory
|
|
|
64
76
|
address.person.should be_saved
|
|
65
77
|
end
|
|
66
78
|
end
|
|
79
|
+
describe "attribute" do
|
|
80
|
+
it "of type boolean supported" do
|
|
81
|
+
factories.define(:person) { |f| f.male true }
|
|
82
|
+
factories.build(:person).male.should be_true
|
|
83
|
+
end
|
|
84
|
+
it "with name open supported" do
|
|
85
|
+
factories.define(:person) { |f| f.open {true} }
|
|
86
|
+
factories.build(:person).open.should be_true
|
|
87
|
+
end
|
|
88
|
+
end
|
|
67
89
|
context "when the module is overridden" do
|
|
68
90
|
before do
|
|
69
91
|
factories.use_default_module "MyModule"
|
|
@@ -90,6 +112,11 @@ module Rubory
|
|
|
90
112
|
person = factories.create(:person)
|
|
91
113
|
person.should be_saved
|
|
92
114
|
end
|
|
115
|
+
it "can override params" do
|
|
116
|
+
person = factories.create(:person, :name => "overridden")
|
|
117
|
+
person.should be_saved
|
|
118
|
+
person.name.should == "overridden"
|
|
119
|
+
end
|
|
93
120
|
end
|
|
94
121
|
|
|
95
122
|
describe "valid attributes" do
|
|
@@ -100,12 +127,18 @@ module Rubory
|
|
|
100
127
|
end
|
|
101
128
|
end
|
|
102
129
|
it "returns the attributes from the definition" do
|
|
103
|
-
factories.define :sequel_person do
|
|
104
|
-
name "name"
|
|
130
|
+
factories.define :sequel_person do |f|
|
|
131
|
+
f.name "name"
|
|
105
132
|
end
|
|
106
133
|
factories.attributes_for(:sequel_person).should == {:name => 'name'}
|
|
107
134
|
end
|
|
108
135
|
|
|
136
|
+
it "returns the attributes from the definition" do
|
|
137
|
+
factories.define :sequel_person do |f|
|
|
138
|
+
f.name "name"
|
|
139
|
+
end
|
|
140
|
+
factories.attributes_for(:sequel_person, :name => 'overridden').should == {:name => 'overridden'}
|
|
141
|
+
end
|
|
109
142
|
end
|
|
110
143
|
context "object responds to :attributes" do
|
|
111
144
|
class ArPerson < Model
|
|
@@ -114,8 +147,8 @@ module Rubory
|
|
|
114
147
|
end
|
|
115
148
|
end
|
|
116
149
|
it "returns the attributes from the definition" do
|
|
117
|
-
factories.define :ar_person do
|
|
118
|
-
name "name"
|
|
150
|
+
factories.define :ar_person do |f|
|
|
151
|
+
f.name "name"
|
|
119
152
|
end
|
|
120
153
|
factories.attributes_for(:ar_person).should == {:name => 'name'}
|
|
121
154
|
end
|
|
@@ -13,6 +13,7 @@ module Qcourses
|
|
|
13
13
|
describe "get trainings" do
|
|
14
14
|
|
|
15
15
|
context "when no repository contigured" do
|
|
16
|
+
before(:each) { CourseRepository.configure nil }
|
|
16
17
|
it "shows error" do
|
|
17
18
|
get url
|
|
18
19
|
last_response.should be_ok
|
|
@@ -21,8 +22,7 @@ module Qcourses
|
|
|
21
22
|
end
|
|
22
23
|
|
|
23
24
|
context "when repository configured" do
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
attr_reader :courses
|
|
26
26
|
it "shows the list of trainings" do
|
|
27
27
|
courses.create_course identification: 'training1', name: 'training 1'
|
|
28
28
|
courses.create_course identification: 'training2', name: 'training 2'
|
|
@@ -4,8 +4,8 @@ require 'capybara/rspec'
|
|
|
4
4
|
module Qcourses
|
|
5
5
|
|
|
6
6
|
describe EventsController, :type => :request do
|
|
7
|
+
attr_reader :courses
|
|
7
8
|
let(:app) { Capybara.app = EventsController }
|
|
8
|
-
let!(:courses) { CourseRepository.in_memory }
|
|
9
9
|
|
|
10
10
|
shared_examples_for "an_event_lister" do
|
|
11
11
|
context "when course repository not configured" do
|
|
@@ -22,7 +22,7 @@ module Qcourses
|
|
|
22
22
|
let!(:course1) { courses.create_course identification: 'agile_engineering', name: 'Agile Engineering' }
|
|
23
23
|
|
|
24
24
|
describe "get '/events'" do
|
|
25
|
-
context "when events
|
|
25
|
+
context "when events planned" do
|
|
26
26
|
let!(:planned) { Event.create(course_id: 'agile_engineering', from: Date.tomorrow, to: Date.tomorrow, :location => "Tilburg") }
|
|
27
27
|
it "renders events" do
|
|
28
28
|
get url
|
|
@@ -69,12 +69,11 @@ module Qcourses
|
|
|
69
69
|
|
|
70
70
|
describe 'get admin edit' do
|
|
71
71
|
let!(:course1) { courses.create_course identification: 'agile_engineering', name: 'Agile Engineering' }
|
|
72
|
-
let
|
|
73
|
-
let (:url) { "/admin/events/edit/#{event.id}" }
|
|
72
|
+
let!(:event) { Rubory.create :event }
|
|
74
73
|
|
|
75
74
|
it "should render a form" do
|
|
76
75
|
event.update :course_id => course1.identification
|
|
77
|
-
get
|
|
76
|
+
get "/admin/events/edit/#{event.id}"
|
|
78
77
|
last_response.should be_ok
|
|
79
78
|
last_body.should have_selector("form#events[@method='post']")
|
|
80
79
|
last_body.find("form#events")['action'].should match("/admin/events/#{event.id}")
|
|
@@ -83,12 +82,18 @@ module Qcourses
|
|
|
83
82
|
last_body.should have_selector("form#events input[@name='event[to]'][@value='#{event.to.strftime("%d-%m-%Y")}']")
|
|
84
83
|
last_body.should have_selector("form#events select[@name='event[course_id]'] option[@value='#{event.course_id}']")
|
|
85
84
|
end
|
|
85
|
+
it "should renders a form for the correct event" do
|
|
86
|
+
event = Rubory.create :event
|
|
87
|
+
event.update :course_id => course1.identification
|
|
88
|
+
get "/admin/events/edit/#{event.id}"
|
|
89
|
+
last_body.find("form#events")['action'].should match("/admin/events/#{event.id}")
|
|
90
|
+
end
|
|
86
91
|
end
|
|
87
92
|
|
|
88
93
|
describe 'post admin' do
|
|
89
94
|
let (:url) { '/admin/events' }
|
|
90
95
|
let (:last_body) { last_response.body }
|
|
91
|
-
let (:event_parameters) {
|
|
96
|
+
let (:event_parameters) { Rubory.attributes_for(:event) }
|
|
92
97
|
|
|
93
98
|
context "on valid parameters" do
|
|
94
99
|
it "should create an event" do
|
|
@@ -116,15 +121,16 @@ module Qcourses
|
|
|
116
121
|
|
|
117
122
|
describe 'put admin' do
|
|
118
123
|
let!(:course1) { courses.create_course identification: 'agile_engineering', name: 'Agile Engineering' }
|
|
119
|
-
let
|
|
124
|
+
let!(:event) { Rubory.create :event }
|
|
120
125
|
let (:url) { "/admin/events/#{event.id}" }
|
|
121
|
-
let (:event_parameters) {
|
|
126
|
+
let (:event_parameters) { Rubory.attributes_for(:event).merge(:max_participants => 1) }
|
|
122
127
|
|
|
123
128
|
context "on valid parameters" do
|
|
124
|
-
it "should
|
|
129
|
+
it "should update the event" do
|
|
125
130
|
expect {
|
|
126
131
|
put url, event: event_parameters
|
|
127
|
-
}.
|
|
132
|
+
}.not_to change {Event.count}
|
|
133
|
+
event.reload.max_participants.should == 1
|
|
128
134
|
end
|
|
129
135
|
|
|
130
136
|
it "should redirect back to list" do
|
|
@@ -4,9 +4,9 @@ module Qcourses
|
|
|
4
4
|
|
|
5
5
|
describe RegistrationsController, :type => :request do
|
|
6
6
|
include Sinatra::Helpers
|
|
7
|
+
attr_reader :courses
|
|
7
8
|
let(:app) { Capybara.app = RegistrationsController }
|
|
8
9
|
let(:event) { Rubory.create :event }
|
|
9
|
-
let!(:courses) { CourseRepository.in_memory }
|
|
10
10
|
|
|
11
11
|
describe 'get new' do
|
|
12
12
|
def get_url(id)
|
|
@@ -52,6 +52,7 @@ module Qcourses
|
|
|
52
52
|
end
|
|
53
53
|
it "creates a registration" do
|
|
54
54
|
expect { post post_url(event.id), valid_registration }.to change { Registration.count }.by(1)
|
|
55
|
+
Registration.order(:id).last.event.should == event
|
|
55
56
|
end
|
|
56
57
|
it "creates a company" do
|
|
57
58
|
expect { post post_url(event.id), valid_registration }.to change { Company.count }.by(1)
|
|
@@ -59,11 +60,17 @@ module Qcourses
|
|
|
59
60
|
it "creates an employee" do
|
|
60
61
|
expect { post post_url(event.id), valid_registration }.to change { Employee.count }.by(1)
|
|
61
62
|
end
|
|
63
|
+
it "sends a confirmation to emloyee" do
|
|
64
|
+
Postman.should_receive(:deliver_registration_notification).with(RegistrationNotification.new(Employee.new(valid_participant), event))
|
|
65
|
+
Postman.should_receive(:deliver_registration_confirmation).with(valid_participant[:email], RegistrationNotification.new(Employee.new(valid_participant), event))
|
|
66
|
+
post post_url(event.id), valid_registration
|
|
67
|
+
end
|
|
62
68
|
context "with more employees" do
|
|
63
69
|
let!(:another_participant) { Rubory.attributes_for :employee }
|
|
64
70
|
let(:participants) { [valid_participant, another_participant] }
|
|
65
71
|
it "creates more registrations" do
|
|
66
72
|
expect { post post_url(event.id), valid_registration }.to change { Registration.count }.by(2)
|
|
73
|
+
Registration.order(:id).last.event.should == event
|
|
67
74
|
end
|
|
68
75
|
it "creates a company" do
|
|
69
76
|
expect { post post_url(event.id), valid_registration }.to change { Company.count }.by(1)
|
|
@@ -23,16 +23,32 @@ module Qcourses
|
|
|
23
23
|
end
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
+
describe "querying" do
|
|
27
|
+
context "on id" do
|
|
28
|
+
it "returns the event if it exists" do
|
|
29
|
+
existing = Rubory.create :event
|
|
30
|
+
Event.find(existing.id).should == existing
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
26
35
|
describe "attributes" do
|
|
27
36
|
|
|
28
|
-
let(:
|
|
37
|
+
let(:event_attributes) { Rubory.attributes_for :event, course_id: 'ae', location_id: nil }
|
|
38
|
+
let(:subject) { Event.new event_attributes }
|
|
29
39
|
its(:from) { should be_a(Time) }
|
|
30
|
-
its(:from) { should ==
|
|
40
|
+
its(:from) { should == event_attributes[:from] }
|
|
31
41
|
its(:to) { should be_a(Time) }
|
|
42
|
+
its(:open?) { should be_true }
|
|
43
|
+
its(:registrations) { should be_empty }
|
|
32
44
|
|
|
45
|
+
context "when no more participants allowed" do
|
|
46
|
+
before { subject.max_participants = 0 }
|
|
47
|
+
its(:open?) { should be_false }
|
|
48
|
+
end
|
|
33
49
|
|
|
34
50
|
describe "from course" do
|
|
35
|
-
let(:course_repository) {
|
|
51
|
+
let(:course_repository) { @courses }
|
|
36
52
|
let!(:course) { course_repository.create_course :identification => 'ae', :name => "AE", :subtitle => 'learn ae' }
|
|
37
53
|
its(:name) { should == course.name }
|
|
38
54
|
its(:subtitle) { should == course.subtitle }
|
|
@@ -44,6 +60,7 @@ module Qcourses
|
|
|
44
60
|
end
|
|
45
61
|
end
|
|
46
62
|
|
|
63
|
+
|
|
47
64
|
describe 'location' do
|
|
48
65
|
it "is converted to a location object" do
|
|
49
66
|
subject.location = "Tilburg"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Qcourses
|
|
4
|
+
describe Postman do
|
|
5
|
+
before { deliveries.clear }
|
|
6
|
+
|
|
7
|
+
let(:employee) { Rubory.build(:employee) }
|
|
8
|
+
let(:event) { Rubory.build(:event) }
|
|
9
|
+
|
|
10
|
+
shared_examples_for "a_problematic_delivery" do
|
|
11
|
+
it "throws an exception if pony throws one" do
|
|
12
|
+
Pony.stub(:mail).and_raise "some exception"
|
|
13
|
+
expect {
|
|
14
|
+
delivery
|
|
15
|
+
}.to raise_exception RuntimeError
|
|
16
|
+
end
|
|
17
|
+
it "swallows exception if set to do so" do
|
|
18
|
+
Postman.allow_delivery_failure
|
|
19
|
+
Pony.stub(:mail).and_raise "some exception"
|
|
20
|
+
expect {
|
|
21
|
+
delivery
|
|
22
|
+
}.to_not raise_exception
|
|
23
|
+
Postman.dont_allow_delivery_failure
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "registration confirmation" do
|
|
28
|
+
|
|
29
|
+
subject do
|
|
30
|
+
Postman.deliver_registration_confirmation("rob@blah.nl", RegistrationNotification.new(employee, event))
|
|
31
|
+
deliveries.last
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it { should deliver_to("rob@blah.nl") }
|
|
35
|
+
it { should deliver_from("info@qwan.it") }
|
|
36
|
+
it { should have_subject(/Thank you.*registration.*#{event.name}/) }
|
|
37
|
+
|
|
38
|
+
it_should_behave_like "a_problematic_delivery" do
|
|
39
|
+
let(:delivery) { subject }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "registration notification" do
|
|
44
|
+
|
|
45
|
+
subject do
|
|
46
|
+
Postman.deliver_registration_notification(RegistrationNotification.new(employee, event))
|
|
47
|
+
deliveries.last
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it { should deliver_to(Postman::NOTIFICATION_ADDRESS) }
|
|
51
|
+
it { should deliver_from(Postman::FROM_ADDRESS) }
|
|
52
|
+
it { should have_subject(/Registration.*#{event.name}/) }
|
|
53
|
+
|
|
54
|
+
it_should_behave_like "a_problematic_delivery" do
|
|
55
|
+
let(:delivery) { subject }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
@@ -13,8 +13,14 @@ module Qcourses
|
|
|
13
13
|
reloaded.should == subject
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
it "adds the registration to the event" do
|
|
17
|
+
subject.save
|
|
18
|
+
event.registrations.should include(subject)
|
|
19
|
+
end
|
|
20
|
+
|
|
16
21
|
it { should reject_values(nil).for(:employee) }
|
|
17
22
|
it { should reject_values(nil).for(:event) }
|
|
23
|
+
|
|
18
24
|
end
|
|
19
25
|
end
|
|
20
26
|
|
|
@@ -101,13 +101,19 @@ module Qcourses
|
|
|
101
101
|
html_for(select_for(:employee, :company_id)).should have_selector("select[name='employee[company_id]']")
|
|
102
102
|
html_for(select_for(@employee, :company_id)).should have_selector("select[name='employee[company_id]']")
|
|
103
103
|
end
|
|
104
|
-
it 'creates
|
|
104
|
+
it 'creates options' do
|
|
105
105
|
options = [["99", "Other Company"]]
|
|
106
106
|
options << [@employee.company_id.to_s, "Company"]
|
|
107
107
|
html_for(select_for(:employee, :company_id, options)).should have_selector("select[name='employee[company_id]'] option[value='99']", :text => "Other Company")
|
|
108
108
|
html_for(select_for(:employee, :company_id, options)).should have_selector("select[name='employee[company_id]'] option[value='#{@employee.company_id}'][selected='selected']", :text => "Company")
|
|
109
109
|
end
|
|
110
|
-
it '
|
|
110
|
+
it 'accepts integers for option values' do
|
|
111
|
+
options = [[99, "Other Company"]]
|
|
112
|
+
options << [@employee.company_id, "Company"]
|
|
113
|
+
html_for(select_for(:employee, :company_id, options)).should have_selector("select[name='employee[company_id]'] option[value='99']", :text => "Other Company")
|
|
114
|
+
html_for(select_for(:employee, :company_id, options)).should have_selector("select[name='employee[company_id]'] option[value='#{@employee.company_id}'][selected='selected']", :text => "Company")
|
|
115
|
+
end
|
|
116
|
+
it 'can have a class and or id' do
|
|
111
117
|
html_for(select_for(:employee, :company_id, nil, :class => 'short')).should have_selector("select[name='employee[company_id]'][class='short']")
|
|
112
118
|
html_for(select_for(:employee, :company_id, nil, :id => 'my_id')).should have_selector("select#my_id")
|
|
113
119
|
end
|
|
@@ -119,7 +125,7 @@ module Qcourses
|
|
|
119
125
|
end
|
|
120
126
|
end
|
|
121
127
|
|
|
122
|
-
describe "event_registration_link"
|
|
128
|
+
describe "event_registration_link" do
|
|
123
129
|
def html_for(result)
|
|
124
130
|
Capybara.string(result)
|
|
125
131
|
end
|
|
@@ -128,11 +134,11 @@ module Qcourses
|
|
|
128
134
|
end
|
|
129
135
|
let(:event) { Rubory.build :event }
|
|
130
136
|
it "contains a registration link" do
|
|
131
|
-
|
|
132
|
-
|
|
137
|
+
result = html_for(event_registration_link(event))
|
|
138
|
+
result.should have_selector("a[href='/registrations/new/#{event.id}']")
|
|
133
139
|
end
|
|
134
140
|
it "contains no registration link if event is closed" do
|
|
135
|
-
event.open
|
|
141
|
+
event.stub :open? => false
|
|
136
142
|
html_for(event_registration_link(event)).should_not have_selector("a[href='/registrations/new/#{event.id}']")
|
|
137
143
|
html_for(event_registration_link(event)).should have_content("closed")
|
|
138
144
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -8,6 +8,8 @@ require 'rspec'
|
|
|
8
8
|
require 'qcourses'
|
|
9
9
|
require 'rack/test'
|
|
10
10
|
require 'capybara'
|
|
11
|
+
require 'pony'
|
|
12
|
+
require 'email_spec'
|
|
11
13
|
|
|
12
14
|
Qcourses.configure do |config|
|
|
13
15
|
config.root = File.expand_path('..',File.dirname(__FILE__))
|
|
@@ -24,6 +26,7 @@ class RSpec::Core::ExampleGroup
|
|
|
24
26
|
super
|
|
25
27
|
subclass.around do |example|
|
|
26
28
|
Qcourses::CourseRepository.destroy
|
|
29
|
+
|
|
27
30
|
Sequel::Model.db.transaction(:rollback=>:always){example.call}
|
|
28
31
|
end
|
|
29
32
|
end
|
|
@@ -32,7 +35,10 @@ end
|
|
|
32
35
|
RSpec.configure do |config|
|
|
33
36
|
config.include Rack::Test::Methods
|
|
34
37
|
config.include TestFiles
|
|
38
|
+
config.include EmailSpec::Matchers
|
|
39
|
+
config.include EmailSpec::Helpers
|
|
35
40
|
config.filter_run_excluding :broken => true
|
|
36
41
|
config.filter_run :focus => true
|
|
37
42
|
config.run_all_when_everything_filtered = true
|
|
43
|
+
config.before(:each) { @courses = Qcourses::CourseRepository.in_memory }
|
|
38
44
|
end
|
data/spec/support/factories.rb
CHANGED
|
@@ -2,23 +2,25 @@ require 'factories'
|
|
|
2
2
|
require 'qcourses/date_ex'
|
|
3
3
|
Rubory.use_default_module('Qcourses')
|
|
4
4
|
|
|
5
|
-
Rubory.define(:company) do
|
|
6
|
-
name { |n| "company_#{n}" }
|
|
7
|
-
contact_person "some contact"
|
|
8
|
-
contact_email { |n| "contact_#{n}@email.com" }
|
|
9
|
-
invoice_address "some address"
|
|
10
|
-
postal_code "1234 AA"
|
|
11
|
-
city "Amsterdam"
|
|
5
|
+
Rubory.define(:company) do |f|
|
|
6
|
+
f.name { |n| "company_#{n}" }
|
|
7
|
+
f.contact_person "some contact"
|
|
8
|
+
f.contact_email { |n| "contact_#{n}@email.com" }
|
|
9
|
+
f.invoice_address "some address"
|
|
10
|
+
f.postal_code "1234 AA"
|
|
11
|
+
f.city "Amsterdam"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
Rubory.define(:employee) do
|
|
15
|
-
name "some employee"
|
|
16
|
-
email { |n| "email_#{n}@qwan.it" }
|
|
17
|
-
associate :company
|
|
14
|
+
Rubory.define(:employee) do |f|
|
|
15
|
+
f.name "some employee"
|
|
16
|
+
f.email { |n| "email_#{n}@qwan.it" }
|
|
17
|
+
f.associate :company
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
Rubory.define(:event) do
|
|
21
|
-
from { Date.tomorrow }
|
|
22
|
-
to { Date.tomorrow.tomorrow }
|
|
23
|
-
|
|
20
|
+
Rubory.define(:event) do |f|
|
|
21
|
+
f.from { Date.tomorrow }
|
|
22
|
+
f.to { Date.tomorrow.tomorrow }
|
|
23
|
+
f.open true
|
|
24
|
+
f.max_participants 14
|
|
25
|
+
f.location "Tilburg"
|
|
24
26
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: qcourses
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.9
|
|
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: 2012-04-
|
|
12
|
+
date: 2012-04-27 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: sinatra
|
|
@@ -18,7 +18,7 @@ dependencies:
|
|
|
18
18
|
requirements:
|
|
19
19
|
- - ~>
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
|
-
version: 1.
|
|
21
|
+
version: '1.3'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -26,7 +26,7 @@ dependencies:
|
|
|
26
26
|
requirements:
|
|
27
27
|
- - ~>
|
|
28
28
|
- !ruby/object:Gem::Version
|
|
29
|
-
version: 1.
|
|
29
|
+
version: '1.3'
|
|
30
30
|
- !ruby/object:Gem::Dependency
|
|
31
31
|
name: haml
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -75,6 +75,22 @@ dependencies:
|
|
|
75
75
|
- - ~>
|
|
76
76
|
- !ruby/object:Gem::Version
|
|
77
77
|
version: 1.3.5
|
|
78
|
+
- !ruby/object:Gem::Dependency
|
|
79
|
+
name: pony
|
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
|
81
|
+
none: false
|
|
82
|
+
requirements:
|
|
83
|
+
- - ~>
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '1.4'
|
|
86
|
+
type: :runtime
|
|
87
|
+
prerelease: false
|
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
89
|
+
none: false
|
|
90
|
+
requirements:
|
|
91
|
+
- - ~>
|
|
92
|
+
- !ruby/object:Gem::Version
|
|
93
|
+
version: '1.4'
|
|
78
94
|
- !ruby/object:Gem::Dependency
|
|
79
95
|
name: rspec
|
|
80
96
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -139,6 +155,38 @@ dependencies:
|
|
|
139
155
|
- - ! '>='
|
|
140
156
|
- !ruby/object:Gem::Version
|
|
141
157
|
version: '0'
|
|
158
|
+
- !ruby/object:Gem::Dependency
|
|
159
|
+
name: shotgun
|
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
|
161
|
+
none: false
|
|
162
|
+
requirements:
|
|
163
|
+
- - ! '>='
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '0'
|
|
166
|
+
type: :development
|
|
167
|
+
prerelease: false
|
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
169
|
+
none: false
|
|
170
|
+
requirements:
|
|
171
|
+
- - ! '>='
|
|
172
|
+
- !ruby/object:Gem::Version
|
|
173
|
+
version: '0'
|
|
174
|
+
- !ruby/object:Gem::Dependency
|
|
175
|
+
name: email_spec
|
|
176
|
+
requirement: !ruby/object:Gem::Requirement
|
|
177
|
+
none: false
|
|
178
|
+
requirements:
|
|
179
|
+
- - ! '>='
|
|
180
|
+
- !ruby/object:Gem::Version
|
|
181
|
+
version: '0'
|
|
182
|
+
type: :development
|
|
183
|
+
prerelease: false
|
|
184
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
185
|
+
none: false
|
|
186
|
+
requirements:
|
|
187
|
+
- - ! '>='
|
|
188
|
+
- !ruby/object:Gem::Version
|
|
189
|
+
version: '0'
|
|
142
190
|
description: Small course event moduel for qinatra site - added as middleware
|
|
143
191
|
email:
|
|
144
192
|
- rob@gqwan.it
|
|
@@ -179,6 +227,7 @@ files:
|
|
|
179
227
|
- lib/qcourses/models/course_repository.rb
|
|
180
228
|
- lib/qcourses/models/event.rb
|
|
181
229
|
- lib/qcourses/models/location.rb
|
|
230
|
+
- lib/qcourses/models/postman.rb
|
|
182
231
|
- lib/qcourses/models/registration.rb
|
|
183
232
|
- lib/qcourses/qcourses.rake.rb
|
|
184
233
|
- lib/qcourses/renderers.rb
|
|
@@ -201,6 +250,7 @@ files:
|
|
|
201
250
|
- spec/qcourses/models/course_repository_spec.rb
|
|
202
251
|
- spec/qcourses/models/event_spec.rb
|
|
203
252
|
- spec/qcourses/models/location_spec.rb
|
|
253
|
+
- spec/qcourses/models/postman_spec.rb
|
|
204
254
|
- spec/qcourses/models/registration_spec.rb
|
|
205
255
|
- spec/qcourses/renderers_spec.rb
|
|
206
256
|
- spec/qcourses/string_ex_spec.rb
|