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.
Files changed (37) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +4 -0
  3. data/Rakefile +4 -6
  4. data/lib/cukedep/application.rb +89 -91
  5. data/lib/cukedep/cli/cmd-line.rb +0 -7
  6. data/lib/cukedep/config.rb +70 -74
  7. data/lib/cukedep/constants.rb +1 -1
  8. data/lib/cukedep/cuke-runner.rb +0 -5
  9. data/lib/cukedep/customization.rb +0 -5
  10. data/lib/cukedep/feature-model.rb +1 -7
  11. data/lib/cukedep/feature-rep.rb +0 -4
  12. data/lib/cukedep/file-action.rb +209 -221
  13. data/lib/cukedep/gherkin-facade.rb +7 -10
  14. data/lib/cukedep/gherkin-listener.rb +82 -89
  15. data/lib/cukedep/hook-dsl.rb +0 -4
  16. data/lib/cukedep/sandbox.rb +0 -5
  17. data/sample/features/step_definitions/steps.rb +30 -26
  18. data/sample/features/support/env.rb +1 -1
  19. data/sample/model/model.rb +198 -205
  20. data/sample/result.html +1 -1
  21. data/spec/cukedep/application_spec.rb +15 -16
  22. data/spec/cukedep/cli/cmd-line_spec.rb +13 -16
  23. data/spec/cukedep/cuke-runner_spec.rb +55 -61
  24. data/spec/cukedep/customization_spec.rb +21 -26
  25. data/spec/cukedep/debug-file-action.rb +12 -10
  26. data/spec/cukedep/feature-model_spec.rb +13 -16
  27. data/spec/cukedep/feature-rep_spec.rb +4 -7
  28. data/spec/cukedep/file-action_spec.rb +18 -34
  29. data/spec/cukedep/file-parsing.rb +9 -11
  30. data/spec/cukedep/gherkin-facade_spec.rb +3 -8
  31. data/spec/cukedep/gherkin-listener_spec.rb +10 -12
  32. data/spec/cukedep/hook-dsl_spec.rb +6 -9
  33. data/spec/cukedep/sample_features/cukedep.rake +44 -37
  34. data/spec/cukedep/sample_features/cukedep_hooks.rb +2 -2
  35. data/spec/cukedep/sample_features/dependencies.dot +1 -1
  36. data/templates/rake.erb +36 -29
  37. 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
- class FeatureFileRep
10
- attr_reader(:filepath)
11
- attr(:feature, true)
12
-
13
- def initialize(aFilepath)
14
- @filepath = aFilepath
15
- end
16
-
17
- def basename()
18
- File.basename(filepath)
19
- end
20
- end # class
21
-
22
- # A ParserListener listens to all the formatting events
23
- # emitted by the Gherkin parser.
24
- # It converts the received the feature file elements and builds
25
- # a representation of the feature files that is appropriate
26
- # for the Cukedep application.
27
- class GherkinListener
28
- # The list of feature files encountered so far
29
- attr_reader(:feature_files)
30
-
31
- # Internal representation of the feature being parsed
32
- attr(:current_feature, true)
33
-
34
- def initialize()
35
- @feature_files = []
36
- end
37
-
38
- ######################################
39
- # Event listening methods
40
- ######################################
41
-
42
- # Called when beginning the parsing of a feature file.
43
- # featureURI: path + filename of feature file.
44
- def uri(featureURI)
45
- new_file = FeatureFileRep.new(featureURI)
46
- feature_files << new_file
47
- end
48
-
49
- # aFeature is a Gherkin::Formatter::Model::Feature instance
50
- def feature(aFeature)
51
- tag_names = aFeature.tags.map(&:name)
52
- @current_feature = feature_files.last.feature = FeatureRep.new(tag_names)
53
- end
54
-
55
- # aBackground is a Gherkin::Formatter::Model::Background instance
56
- def background(_aBackground)
57
- ; # Do nothing
58
- end
59
-
60
- # aScenario is a Gherkin::Formatter::Model::Scenario instance
61
- def scenario(_aScenario)
62
- ; # Do nothing
63
- end
64
-
65
- # aScenarioOutline is a Gherkin::Formatter::Model::ScenarioOutline instance
66
- def scenario_outline(_aScenarioOutline)
67
- ; # Do nothing
68
- end
69
-
70
- # theExamples is a Gherkin::Formatter::Model::Examples instance
71
- def examples(_theExamples)
72
- ; # Do nothing
73
- end
74
-
75
- # aStep is a Gherkin::Formatter::Model::Step instance
76
- def step(_aStep)
77
- ; # Do nothing
78
- end
79
-
80
- # End of feature file notification.
81
- def eof()
82
- ; # Do nothing
83
- end
84
-
85
-
86
- # Catch all method
87
- def method_missing(message, *_args)
88
- puts "Method #{message} is not implemented (yet)."
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
@@ -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
@@ -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
- $store.zap_catalogue!()
9
+ store.zap_catalogue!
6
10
  end
7
11
 
8
12
  Given(/^I add the video "(.*?)" to the catalogue$/) do |a_title|
9
- $store.add_video(a_title)
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($store.search_video(a_title)).to be_nil
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 = $store.search_video(a_title)
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 = $store.search_video(a_title)
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
- $store.remove_video(found_video)
29
+ store.remove_video(found_video)
26
30
  end
27
31
 
28
32
  Given(/^there is no member yet$/) do
29
- $store.send(:zap_members!) # Why is this method seen as private?
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($store.search_member(member_name)).to be_nil
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($store.search_member(member_name)).not_to be_nil
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
- $store.add_member(member_name)
46
+ store.add_member(member_name)
43
47
  end
44
48
 
45
49
 
46
50
  Given(/^there is no registered user$/) do
47
- $store.zap_users!
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($store.search_user(@entered_credential)).to be_nil
56
- puts "Invalid user credential"
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
- $store.add_user(credential)
64
+ store.add_user(credential)
61
65
  end
62
66
 
63
67
  Then(/^I should see a welcome message$/) do
64
- expect($store.search_user(@entered_credential)).not_to be_nil
65
- puts "Welcome to the rental application."
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 = $store.search_video(a_title)
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 = $store.search_member(member_name)
78
+ member = store.search_member(member_name)
75
79
  expect(member).not_to be_nil
76
- $store.add_rental(found_video, member)
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 "Rental registered." if @confirm_rental
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 "Rental refused." unless @confirm_rental
90
+ puts 'Rental refused.' unless @confirm_rental
87
91
  end
88
92
 
89
93
 
90
- When(/^I register the return of "(.*?)" from "(.*?)"$/) do |a_title, member_name|
91
- rental = $store.search_rental(a_title)
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
- $store.close_rental(rental)
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 "Return registered." if @confirm_return
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
@@ -9,4 +9,4 @@ AfterConfiguration do |_|
9
9
  $store = Sample::RentalStore.new
10
10
  end
11
11
 
12
- # End of file
12
+ # End of file
@@ -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
- # Assumption: the store has one examplar only of a video title
11
- Video = Struct.new(
12
- :title, # Title of the video (as an identifier)
13
- :state # Current state of the video
14
- )
15
-
16
- # A member of the video store, i.e. a person that is allowed
17
- # to rent a video from the store.
18
- Member = Struct.new(
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