cukedep 0.1.10 → 0.1.11
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.
- checksums.yaml +8 -8
- data/CHANGELOG.md +4 -0
- data/Rakefile +4 -6
- data/lib/cukedep/application.rb +89 -91
- data/lib/cukedep/cli/cmd-line.rb +0 -7
- data/lib/cukedep/config.rb +70 -74
- data/lib/cukedep/constants.rb +1 -1
- data/lib/cukedep/cuke-runner.rb +0 -5
- data/lib/cukedep/customization.rb +0 -5
- data/lib/cukedep/feature-model.rb +1 -7
- data/lib/cukedep/feature-rep.rb +0 -4
- data/lib/cukedep/file-action.rb +209 -221
- data/lib/cukedep/gherkin-facade.rb +7 -10
- data/lib/cukedep/gherkin-listener.rb +82 -89
- data/lib/cukedep/hook-dsl.rb +0 -4
- data/lib/cukedep/sandbox.rb +0 -5
- data/sample/features/step_definitions/steps.rb +30 -26
- data/sample/features/support/env.rb +1 -1
- data/sample/model/model.rb +198 -205
- data/sample/result.html +1 -1
- data/spec/cukedep/application_spec.rb +15 -16
- data/spec/cukedep/cli/cmd-line_spec.rb +13 -16
- data/spec/cukedep/cuke-runner_spec.rb +55 -61
- data/spec/cukedep/customization_spec.rb +21 -26
- data/spec/cukedep/debug-file-action.rb +12 -10
- data/spec/cukedep/feature-model_spec.rb +13 -16
- data/spec/cukedep/feature-rep_spec.rb +4 -7
- data/spec/cukedep/file-action_spec.rb +18 -34
- data/spec/cukedep/file-parsing.rb +9 -11
- data/spec/cukedep/gherkin-facade_spec.rb +3 -8
- data/spec/cukedep/gherkin-listener_spec.rb +10 -12
- data/spec/cukedep/hook-dsl_spec.rb +6 -9
- data/spec/cukedep/sample_features/cukedep.rake +44 -37
- data/spec/cukedep/sample_features/cukedep_hooks.rb +2 -2
- data/spec/cukedep/sample_features/dependencies.dot +1 -1
- data/templates/rake.erb +36 -29
- metadata +2 -2
@@ -4,25 +4,24 @@ require 'gherkin'
|
|
4
4
|
require 'gherkin/lexer/encoding'
|
5
5
|
|
6
6
|
module Cukedep # This module is used as a namespace
|
7
|
-
|
8
7
|
# Facade design pattern: A facade is an object that provides
|
9
8
|
# a simplified interface to a larger body of code.
|
10
9
|
# Here the GherkinFacade class provides basic parsing service.
|
11
10
|
class GherkinFacade
|
12
11
|
# Indicate whether the parsing must be verbose or silent
|
13
12
|
attr_reader(:verbose)
|
14
|
-
|
13
|
+
|
15
14
|
# (External) encoding of the feature files.
|
16
15
|
# It is a string that represents the name of an encoding
|
17
16
|
# as expected by the mode argument of the IO#new method
|
18
17
|
attr_reader(:external_encoding)
|
19
|
-
|
18
|
+
|
20
19
|
|
21
20
|
def initialize(isVerbose, anExternalEncoding)
|
22
21
|
@verbose = isVerbose
|
23
22
|
@external_encoding = anExternalEncoding
|
24
23
|
end
|
25
|
-
|
24
|
+
|
26
25
|
# Parse feature files from the work directory that match
|
27
26
|
# one of the given file name patterns.
|
28
27
|
# Parse events are sent to the passed listener object.
|
@@ -34,22 +33,20 @@ module Cukedep # This module is used as a namespace
|
|
34
33
|
# List all .feature files in work directory that match the pattern
|
35
34
|
filenames = []
|
36
35
|
file_patterns.each { |patt| filenames.concat(Dir.glob(patt)) }
|
37
|
-
|
36
|
+
|
38
37
|
# Parse them
|
39
38
|
filenames.each do |fname|
|
40
39
|
puts " #{fname}" if verbose
|
41
40
|
# To prevent encoding issue, open the file
|
42
41
|
# with an explicit external encoding
|
43
|
-
File.open(fname, "r:#{external_encoding}") do |f|
|
44
|
-
parser.parse(f.read, fname, 0)
|
42
|
+
File.open(fname, "r:#{external_encoding}") do |f|
|
43
|
+
parser.parse(f.read, fname, 0)
|
45
44
|
end
|
46
45
|
end
|
47
|
-
|
46
|
+
|
48
47
|
return aListener
|
49
48
|
end
|
50
|
-
|
51
49
|
end # class
|
52
|
-
|
53
50
|
end # module
|
54
51
|
|
55
52
|
# End of file
|
@@ -4,95 +4,88 @@ require_relative 'feature-rep'
|
|
4
4
|
|
5
5
|
|
6
6
|
module Cukedep # This module is used as a namespace
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
|
-
end # class
|
92
|
-
|
7
|
+
class FeatureFileRep
|
8
|
+
attr_reader(:filepath)
|
9
|
+
attr(:feature, true)
|
10
|
+
|
11
|
+
def initialize(aFilepath)
|
12
|
+
@filepath = aFilepath
|
13
|
+
end
|
14
|
+
|
15
|
+
def basename()
|
16
|
+
File.basename(filepath)
|
17
|
+
end
|
18
|
+
end # class
|
19
|
+
|
20
|
+
# A ParserListener listens to all the formatting events
|
21
|
+
# emitted by the Gherkin parser.
|
22
|
+
# It converts the received the feature file elements and builds
|
23
|
+
# a representation of the feature files that is appropriate
|
24
|
+
# for the Cukedep application.
|
25
|
+
class GherkinListener
|
26
|
+
# The list of feature files encountered so far
|
27
|
+
attr_reader(:feature_files)
|
28
|
+
|
29
|
+
# Internal representation of the feature being parsed
|
30
|
+
attr(:current_feature, true)
|
31
|
+
|
32
|
+
def initialize()
|
33
|
+
@feature_files = []
|
34
|
+
end
|
35
|
+
|
36
|
+
######################################
|
37
|
+
# Event listening methods
|
38
|
+
######################################
|
39
|
+
|
40
|
+
# Called when beginning the parsing of a feature file.
|
41
|
+
# featureURI: path + filename of feature file.
|
42
|
+
def uri(featureURI)
|
43
|
+
new_file = FeatureFileRep.new(featureURI)
|
44
|
+
feature_files << new_file
|
45
|
+
end
|
46
|
+
|
47
|
+
# aFeature is a Gherkin::Formatter::Model::Feature instance
|
48
|
+
def feature(aFeature)
|
49
|
+
tag_names = aFeature.tags.map(&:name)
|
50
|
+
@current_feature = feature_files.last.feature = FeatureRep.new(tag_names)
|
51
|
+
end
|
52
|
+
|
53
|
+
# aBackground is a Gherkin::Formatter::Model::Background instance
|
54
|
+
def background(_aBackground)
|
55
|
+
; # Do nothing
|
56
|
+
end
|
57
|
+
|
58
|
+
# aScenario is a Gherkin::Formatter::Model::Scenario instance
|
59
|
+
def scenario(_aScenario)
|
60
|
+
; # Do nothing
|
61
|
+
end
|
62
|
+
|
63
|
+
# aScenarioOutline is a Gherkin::Formatter::Model::ScenarioOutline instance
|
64
|
+
def scenario_outline(_aScenarioOutline)
|
65
|
+
; # Do nothing
|
66
|
+
end
|
67
|
+
|
68
|
+
# theExamples is a Gherkin::Formatter::Model::Examples instance
|
69
|
+
def examples(_theExamples)
|
70
|
+
; # Do nothing
|
71
|
+
end
|
72
|
+
|
73
|
+
# aStep is a Gherkin::Formatter::Model::Step instance
|
74
|
+
def step(_aStep)
|
75
|
+
; # Do nothing
|
76
|
+
end
|
77
|
+
|
78
|
+
# End of feature file notification.
|
79
|
+
def eof()
|
80
|
+
; # Do nothing
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Catch all method
|
85
|
+
def method_missing(message, *_args)
|
86
|
+
puts "Method #{message} is not implemented (yet)."
|
87
|
+
end
|
88
|
+
end # class
|
93
89
|
end # module
|
94
90
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
91
|
# End of file
|
data/lib/cukedep/hook-dsl.rb
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
module Cukedep # Module used as a namespace
|
5
|
-
|
6
5
|
# Mix-in module that defines the DSL (Domain-Specific Language)
|
7
6
|
# for specifying Cukedep hooks.
|
8
7
|
# A hook is a custom code block that is executed when
|
@@ -74,9 +73,6 @@ module HookDSL
|
|
74
73
|
handler = hooks.nil? ? nil : hooks.fetch(aScope)
|
75
74
|
return handler
|
76
75
|
end
|
77
|
-
|
78
76
|
end # module
|
79
|
-
|
80
77
|
end # module
|
81
|
-
|
82
78
|
# End of file
|
data/lib/cukedep/sandbox.rb
CHANGED
@@ -2,10 +2,8 @@
|
|
2
2
|
|
3
3
|
|
4
4
|
module Cukedep # This module is used as a namespace
|
5
|
-
|
6
5
|
# A context in which hook block codes are run.
|
7
6
|
class Sandbox
|
8
|
-
|
9
7
|
attr_reader(:base_dir)
|
10
8
|
attr_reader(:proj_dir)
|
11
9
|
|
@@ -13,9 +11,6 @@ module Cukedep # This module is used as a namespace
|
|
13
11
|
@base_dir = theBaseDir.dup.freeze
|
14
12
|
@proj_dir = theProjectDir.dup.freeze
|
15
13
|
end
|
16
|
-
|
17
14
|
end # class
|
18
|
-
|
19
15
|
end # module
|
20
|
-
|
21
16
|
# End of file
|
@@ -1,50 +1,54 @@
|
|
1
1
|
# File: steps.rb
|
2
2
|
# Step definitions for a sample Cucumber application
|
3
3
|
|
4
|
+
def store()
|
5
|
+
$store
|
6
|
+
end
|
7
|
+
|
4
8
|
Given(/^the catalogue is empty$/) do
|
5
|
-
|
9
|
+
store.zap_catalogue!
|
6
10
|
end
|
7
11
|
|
8
12
|
Given(/^I add the video "(.*?)" to the catalogue$/) do |a_title|
|
9
|
-
|
13
|
+
store.add_video(a_title)
|
10
14
|
end
|
11
15
|
|
12
16
|
Then(/^I should see the video "(.*?)" as unknown$/) do |a_title|
|
13
|
-
expect(
|
17
|
+
expect(store.search_video(a_title)).to be_nil
|
14
18
|
end
|
15
19
|
|
16
20
|
Then(/^I should see the video "(.*?)" as (available)$/) do |a_title, a_state|
|
17
|
-
found_video =
|
21
|
+
found_video = store.search_video(a_title)
|
18
22
|
expect(found_video.state).to eq(a_state.to_sym)
|
19
23
|
end
|
20
24
|
|
21
25
|
When(/^I remove the video "(.*?)"$/) do |a_title|
|
22
|
-
found_video =
|
26
|
+
found_video = store.search_video(a_title)
|
23
27
|
expect(found_video).not_to be_nil
|
24
28
|
expect(found_video.state).to eq(:available)
|
25
|
-
|
29
|
+
store.remove_video(found_video)
|
26
30
|
end
|
27
31
|
|
28
32
|
Given(/^there is no member yet$/) do
|
29
|
-
|
33
|
+
store.send(:zap_members!) # Why is this method seen as private?
|
30
34
|
end
|
31
35
|
|
32
36
|
Then(/^I should see member "(.*?)" as unknown$/) do |member_name|
|
33
|
-
expect(
|
37
|
+
expect(store.search_member(member_name)).to be_nil
|
34
38
|
end
|
35
39
|
|
36
40
|
Then(/^I should see member "(.*?)" as registered$/) do |member_name|
|
37
|
-
expect(
|
41
|
+
expect(store.search_member(member_name)).not_to be_nil
|
38
42
|
puts "Member #{member_name} is registered."
|
39
43
|
end
|
40
44
|
|
41
45
|
Given(/^I subscribe "(.*?)"$/) do |member_name|
|
42
|
-
|
46
|
+
store.add_member(member_name)
|
43
47
|
end
|
44
48
|
|
45
49
|
|
46
50
|
Given(/^there is no registered user$/) do
|
47
|
-
|
51
|
+
store.zap_users!
|
48
52
|
end
|
49
53
|
|
50
54
|
When(/^I enter the credentials "(.*?)"$/) do |credential|
|
@@ -52,54 +56,54 @@ When(/^I enter the credentials "(.*?)"$/) do |credential|
|
|
52
56
|
end
|
53
57
|
|
54
58
|
Then(/^I should not be authorized$/) do
|
55
|
-
expect(
|
56
|
-
puts
|
59
|
+
expect(store.search_user(@entered_credential)).to be_nil
|
60
|
+
puts 'Invalid user credential'
|
57
61
|
end
|
58
62
|
|
59
63
|
When(/^I register my credentials "(.*?)"$/) do |credential|
|
60
|
-
|
64
|
+
store.add_user(credential)
|
61
65
|
end
|
62
66
|
|
63
67
|
Then(/^I should see a welcome message$/) do
|
64
|
-
expect(
|
65
|
-
puts
|
68
|
+
expect(store.search_user(@entered_credential)).not_to be_nil
|
69
|
+
puts 'Welcome to the rental application.'
|
66
70
|
end
|
67
71
|
|
68
72
|
|
69
73
|
When(/^I register the rental of "(.*?)" for "(.*?)"$/) do |a_title, member_name|
|
70
|
-
found_video =
|
74
|
+
found_video = store.search_video(a_title)
|
71
75
|
expect(found_video).not_to be_nil
|
72
76
|
expect(found_video.state).to eq(:available)
|
73
77
|
|
74
|
-
member =
|
78
|
+
member = store.search_member(member_name)
|
75
79
|
expect(member).not_to be_nil
|
76
|
-
|
80
|
+
store.add_rental(found_video, member)
|
77
81
|
@confirm_rental = true
|
78
82
|
end
|
79
83
|
|
80
84
|
Then(/^I should see the rental confirmed$/) do
|
81
|
-
puts
|
85
|
+
puts 'Rental registered.' if @confirm_rental
|
82
86
|
@confirm_rental = nil
|
83
87
|
end
|
84
88
|
|
85
89
|
Then(/^I should see the rental refused$/) do
|
86
|
-
puts
|
90
|
+
puts 'Rental refused.' unless @confirm_rental
|
87
91
|
end
|
88
92
|
|
89
93
|
|
90
|
-
When(/^I register the return of "(.*?)" from "(.*?)"$/) do |
|
91
|
-
rental =
|
94
|
+
When(/^I register the return of "(.*?)" from "(.*?)"$/) do |title, member_name|
|
95
|
+
rental = store.search_rental(title)
|
92
96
|
expect(rental).not_to be_nil
|
93
97
|
expect(rental.member).to eq(member_name)
|
94
|
-
|
98
|
+
store.close_rental(rental)
|
95
99
|
@confirm_return = true
|
96
100
|
end
|
97
101
|
|
98
102
|
Then(/^I should see the return confirmed$/) do
|
99
|
-
puts
|
103
|
+
puts 'Return registered.' if @confirm_return
|
100
104
|
@confirm_return = nil
|
101
105
|
end
|
102
106
|
|
103
107
|
|
104
108
|
|
105
|
-
# End of file
|
109
|
+
# End of file
|
data/sample/model/model.rb
CHANGED
@@ -1,216 +1,209 @@
|
|
1
1
|
# File: model.rb
|
2
2
|
|
3
3
|
require 'pp'
|
4
|
-
require 'yaml' # Rely on YAML for object persistence
|
4
|
+
require 'yaml' # Rely on YAML for object persistence
|
5
5
|
|
6
6
|
|
7
7
|
# Module used as a namespace
|
8
8
|
module Sample
|
9
|
+
# Assumption: the store has one examplar only of a video title
|
10
|
+
Video = Struct.new(
|
11
|
+
:title, # Title of the video (as an identifier)
|
12
|
+
:state # Current state of the video
|
13
|
+
)
|
14
|
+
|
15
|
+
# A member of the video store, i.e. a person that is allowed
|
16
|
+
# to rent a video from the store.
|
17
|
+
Member = Struct.new(
|
18
|
+
:name # As an identifier
|
19
|
+
)
|
20
|
+
|
21
|
+
# Association object between a Video and a Member.
|
22
|
+
# In our sample model, no rental history is performed
|
23
|
+
Rental = Struct.new(
|
24
|
+
:video, # Use the title of the rented video as key
|
25
|
+
:member # Use the name of the Member as key
|
26
|
+
)
|
27
|
+
|
28
|
+
# The identification of a store rental employee
|
29
|
+
# that is authorized to use the rental software.
|
30
|
+
User = Struct.new(
|
31
|
+
:credential # user credential
|
32
|
+
)
|
33
|
+
|
34
|
+
# Simplistic domain model of a video rental store.
|
35
|
+
class RentalStore
|
36
|
+
MyDir = File.dirname(__FILE__) + '/'
|
37
|
+
CatalogueFile = 'catalogue.yml'
|
38
|
+
MembersFile = 'members.yml'
|
39
|
+
RentalsFile = 'rentals.yml'
|
40
|
+
UsersFile = 'users.yml'
|
41
|
+
|
42
|
+
|
43
|
+
# The list of all videos owned by the store.
|
44
|
+
attr_reader(:catalogue)
|
45
|
+
|
46
|
+
# The list of all Members
|
47
|
+
attr_reader(:members)
|
48
|
+
|
49
|
+
# The list of all open-standing rentals
|
50
|
+
attr_reader(:rentals)
|
51
|
+
|
52
|
+
# The list of application user (credentials)
|
53
|
+
attr_reader(:users)
|
54
|
+
|
55
|
+
def initialize()
|
56
|
+
init_catalogue
|
57
|
+
init_members
|
58
|
+
init_rentals
|
59
|
+
init_users
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
# Clear the catalogue (= make it empty).
|
64
|
+
def zap_catalogue!()
|
65
|
+
catalogue.clear
|
66
|
+
save_catalogue
|
67
|
+
zap_rentals!
|
68
|
+
end
|
69
|
+
|
70
|
+
def zap_members!()
|
71
|
+
members.clear
|
72
|
+
save_members
|
73
|
+
zap_rentals!
|
74
|
+
end
|
75
|
+
|
76
|
+
def zap_users!()
|
77
|
+
users.clear
|
78
|
+
save_users
|
79
|
+
end
|
80
|
+
|
81
|
+
# Search a Video object having the given title
|
82
|
+
def search_video(aTitle)
|
83
|
+
result = catalogue.find { |video| video.title.strip == aTitle.strip }
|
84
|
+
if result.nil?
|
85
|
+
msg = "Video with title '#{aTitle}' isn't in the catalogue."
|
86
|
+
$stderr.puts msg
|
87
|
+
end
|
88
|
+
|
89
|
+
return result
|
90
|
+
end
|
91
|
+
|
92
|
+
def remove_video(aVideo)
|
93
|
+
catalogue.delete(aVideo)
|
94
|
+
save_catalogue
|
95
|
+
end
|
96
|
+
|
97
|
+
# Add a new video to the catalogue
|
98
|
+
def add_video(aTitle)
|
99
|
+
# Simplification: no check for title collision
|
100
|
+
catalogue << Video.new(aTitle, :available)
|
101
|
+
save_catalogue
|
102
|
+
end
|
103
|
+
|
104
|
+
def search_member(aName)
|
105
|
+
mb = members.find { |person| person.name.strip == aName.strip }
|
106
|
+
puts "No member with name #{aName}." if mb.nil?
|
107
|
+
|
108
|
+
return mb
|
109
|
+
end
|
9
110
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
:name # As an identifier
|
20
|
-
)
|
21
|
-
|
22
|
-
# Association object between a Video and a Member.
|
23
|
-
# In our sample model, no rental history is performed
|
24
|
-
Rental = Struct.new(
|
25
|
-
:video, # Use the title of the rented video as key
|
26
|
-
:member # Use the name of the Member as key
|
27
|
-
)
|
28
|
-
|
29
|
-
# The identification of a store rental employee
|
30
|
-
# that is authorized to use the rental software.
|
31
|
-
User = Struct.new(
|
32
|
-
:credential # user credential
|
33
|
-
)
|
34
|
-
|
35
|
-
# Simplistic domain model of a video rental store.
|
36
|
-
class RentalStore
|
37
|
-
MyDir = File.dirname(__FILE__) + '/'
|
38
|
-
CatalogueFile = 'catalogue.yml'
|
39
|
-
MembersFile = 'members.yml'
|
40
|
-
RentalsFile = 'rentals.yml'
|
41
|
-
UsersFile = 'users.yml'
|
42
|
-
|
43
|
-
|
44
|
-
# The list of all videos owned by the store.
|
45
|
-
attr_reader(:catalogue)
|
46
|
-
|
47
|
-
# The list of all Members
|
48
|
-
attr_reader(:members)
|
49
|
-
|
50
|
-
# The list of all open-standing rentals
|
51
|
-
attr_reader(:rentals)
|
52
|
-
|
53
|
-
# The list of application user (credentials)
|
54
|
-
attr_reader(:users)
|
55
|
-
|
56
|
-
def initialize()
|
57
|
-
init_catalogue()
|
58
|
-
init_members()
|
59
|
-
init_rentals()
|
60
|
-
init_users()
|
61
|
-
end
|
62
|
-
|
63
|
-
|
64
|
-
# Clear the catalogue (= make it empty).
|
65
|
-
def zap_catalogue!()
|
66
|
-
catalogue.clear()
|
67
|
-
save_catalogue()
|
68
|
-
zap_rentals!()
|
69
|
-
end
|
70
|
-
|
71
|
-
def zap_members!()
|
72
|
-
members.clear()
|
73
|
-
save_members()
|
74
|
-
zap_rentals!()
|
75
|
-
end
|
76
|
-
|
77
|
-
def zap_users!()
|
78
|
-
users.clear()
|
79
|
-
save_users()
|
80
|
-
end
|
81
|
-
|
82
|
-
# Search a Video object having the given title
|
83
|
-
def search_video(aTitle)
|
84
|
-
result = catalogue.find {|video| video.title.strip == aTitle.strip}
|
85
|
-
if result.nil?
|
86
|
-
msg = "Video with title '#{aTitle}' isn't in the catalogue."
|
87
|
-
$stderr.puts msg
|
88
|
-
end
|
89
|
-
|
90
|
-
return result
|
91
|
-
end
|
92
|
-
|
93
|
-
def remove_video(aVideo)
|
94
|
-
catalogue.delete(aVideo)
|
95
|
-
save_catalogue()
|
96
|
-
end
|
97
|
-
|
98
|
-
# Add a new video to the catalogue
|
99
|
-
def add_video(aTitle)
|
100
|
-
# Simplification: no check for title collision
|
101
|
-
catalogue << Video.new(aTitle, :available)
|
102
|
-
save_catalogue()
|
103
|
-
end
|
104
|
-
|
105
|
-
def search_member(aName)
|
106
|
-
mb = members.find {|person| person.name.strip == aName.strip}
|
107
|
-
puts "No member with name #{aName}." if mb.nil?
|
108
|
-
|
109
|
-
return mb
|
110
|
-
end
|
111
|
-
|
112
|
-
def add_member(aName)
|
113
|
-
# Simplification: no check for name collision
|
114
|
-
members << Member.new(aName)
|
115
|
-
save_members()
|
116
|
-
end
|
117
|
-
|
118
|
-
def search_user(aCredential)
|
119
|
-
users.find {|user| user.credential.strip == aCredential.strip}
|
120
|
-
end
|
121
|
-
|
122
|
-
def add_user(aCredential)
|
123
|
-
# Simplification: no check for credential collision
|
124
|
-
users << User.new(aCredential)
|
125
|
-
save_users()
|
126
|
-
end
|
127
|
-
|
128
|
-
def search_rental(aTitle)
|
129
|
-
rentals.find {|r| r.video.strip == aTitle.strip}
|
130
|
-
end
|
131
|
-
|
132
|
-
def add_rental(aVideo, aMember)
|
133
|
-
rentals << Rental.new(aVideo.title, aMember.name)
|
134
|
-
aVideo.state = :rented
|
135
|
-
save_rentals
|
136
|
-
end
|
137
|
-
|
138
|
-
def close_rental(aRental)
|
139
|
-
returned_video = search_video(aRental.video)
|
140
|
-
returned_video.state = :available
|
141
|
-
rentals.delete(aRental)
|
142
|
-
save_rentals
|
143
|
-
end
|
144
|
-
|
145
|
-
private
|
146
|
-
def init_catalogue()
|
147
|
-
filepath = MyDir + CatalogueFile
|
148
|
-
if File.exist?(filepath)
|
149
|
-
@catalogue = YAML.load_file(filepath)
|
150
|
-
else
|
151
|
-
@catalogue = []
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def init_members()
|
156
|
-
filepath = MyDir + MembersFile
|
157
|
-
if File.exist?(filepath)
|
158
|
-
@members = YAML.load_file(filepath)
|
159
|
-
else
|
160
|
-
@members = []
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
def init_users()
|
165
|
-
filepath = MyDir + UsersFile
|
166
|
-
if File.exist?(filepath)
|
167
|
-
@users = YAML.load_file(filepath)
|
168
|
-
else
|
169
|
-
@users = []
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def init_rentals()
|
174
|
-
filepath = MyDir + RentalsFile
|
175
|
-
if File.exist?(filepath)
|
176
|
-
@rentals = YAML.load_file(filepath)
|
177
|
-
else
|
178
|
-
@rentals = []
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def zap_rentals!()
|
183
|
-
rentals.clear
|
184
|
-
save_rentals()
|
185
|
-
end
|
186
|
-
|
187
|
-
def zap_members!()
|
188
|
-
members.clear
|
189
|
-
save_members()
|
190
|
-
end
|
191
|
-
|
192
|
-
def save_catalogue()
|
193
|
-
filepath = MyDir + CatalogueFile
|
194
|
-
File.open(filepath, 'w') {|f| YAML.dump(catalogue, f)}
|
195
|
-
end
|
196
|
-
|
197
|
-
def save_members()
|
198
|
-
filepath = MyDir + MembersFile
|
199
|
-
File.open(filepath, 'w') {|f| YAML.dump(members, f)}
|
200
|
-
end
|
201
|
-
|
202
|
-
def save_users()
|
203
|
-
filepath = MyDir + UsersFile
|
204
|
-
File.open(filepath, 'w') {|f| YAML.dump(users, f)}
|
205
|
-
end
|
206
|
-
|
207
|
-
def save_rentals()
|
208
|
-
filepath = MyDir + RentalsFile
|
209
|
-
File.open(filepath, 'w') {|f| YAML.dump(rentals, f)}
|
210
|
-
end
|
211
|
-
|
212
|
-
end # class
|
111
|
+
def add_member(aName)
|
112
|
+
# Simplification: no check for name collision
|
113
|
+
members << Member.new(aName)
|
114
|
+
save_members
|
115
|
+
end
|
116
|
+
|
117
|
+
def search_user(aCredential)
|
118
|
+
users.find { |user| user.credential.strip == aCredential.strip }
|
119
|
+
end
|
213
120
|
|
121
|
+
def add_user(aCredential)
|
122
|
+
# Simplification: no check for credential collision
|
123
|
+
users << User.new(aCredential)
|
124
|
+
save_users
|
125
|
+
end
|
126
|
+
|
127
|
+
def search_rental(aTitle)
|
128
|
+
rentals.find { |r| r.video.strip == aTitle.strip }
|
129
|
+
end
|
130
|
+
|
131
|
+
def add_rental(aVideo, aMember)
|
132
|
+
rentals << Rental.new(aVideo.title, aMember.name)
|
133
|
+
aVideo.state = :rented
|
134
|
+
save_rentals
|
135
|
+
end
|
136
|
+
|
137
|
+
def close_rental(aRental)
|
138
|
+
returned_video = search_video(aRental.video)
|
139
|
+
returned_video.state = :available
|
140
|
+
rentals.delete(aRental)
|
141
|
+
save_rentals
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def init_catalogue()
|
147
|
+
filepath = MyDir + CatalogueFile
|
148
|
+
if File.exist?(filepath)
|
149
|
+
@catalogue = YAML.load_file(filepath)
|
150
|
+
else
|
151
|
+
@catalogue = []
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def init_members()
|
156
|
+
filepath = MyDir + MembersFile
|
157
|
+
if File.exist?(filepath)
|
158
|
+
@members = YAML.load_file(filepath)
|
159
|
+
else
|
160
|
+
@members = []
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def init_users()
|
165
|
+
filepath = MyDir + UsersFile
|
166
|
+
if File.exist?(filepath)
|
167
|
+
@users = YAML.load_file(filepath)
|
168
|
+
else
|
169
|
+
@users = []
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def init_rentals()
|
174
|
+
filepath = MyDir + RentalsFile
|
175
|
+
if File.exist?(filepath)
|
176
|
+
@rentals = YAML.load_file(filepath)
|
177
|
+
else
|
178
|
+
@rentals = []
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def zap_rentals!()
|
183
|
+
rentals.clear
|
184
|
+
save_rentals
|
185
|
+
end
|
186
|
+
|
187
|
+
def save_catalogue()
|
188
|
+
filepath = MyDir + CatalogueFile
|
189
|
+
File.open(filepath, 'w') { |f| YAML.dump(catalogue, f) }
|
190
|
+
end
|
191
|
+
|
192
|
+
def save_members()
|
193
|
+
filepath = MyDir + MembersFile
|
194
|
+
File.open(filepath, 'w') { |f| YAML.dump(members, f) }
|
195
|
+
end
|
196
|
+
|
197
|
+
def save_users()
|
198
|
+
filepath = MyDir + UsersFile
|
199
|
+
File.open(filepath, 'w') { |f| YAML.dump(users, f) }
|
200
|
+
end
|
201
|
+
|
202
|
+
def save_rentals()
|
203
|
+
filepath = MyDir + RentalsFile
|
204
|
+
File.open(filepath, 'w') { |f| YAML.dump(rentals, f) }
|
205
|
+
end
|
206
|
+
end # class
|
214
207
|
end # module
|
215
208
|
|
216
|
-
# End of file
|
209
|
+
# End of file
|