ygg 0.0.2 → 1.0.6

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.
@@ -0,0 +1,24 @@
1
+ Feature: Ygg Domain Specific Language
2
+ In order to access ygg features easily
3
+ As a Ygg user
4
+ I want to have a nice DSL
5
+
6
+ Background: All that from the other features
7
+ Given the class User has the field :name
8
+ And extends Record
9
+ And the class Account has the field :amount
10
+ And the class Account has the field :currency
11
+ And extends Record
12
+ And I have the file "emulations/samples/user.ygg"
13
+
14
+ Scenario: Data on session closed
15
+ When I load the file
16
+ And I ask User for records
17
+ Then I should get an user named "Xavier Via"
18
+
19
+ Scenario: Giving path & identifier
20
+ Given the path "emulations/samples"
21
+ And the identifier :user
22
+ When I call ygg with those arguments
23
+ And I ask User for records
24
+ Then I should get an user named "Xavier Via"
@@ -0,0 +1,17 @@
1
+ Feature: Event managing
2
+ In order to recall data from past interactions
3
+ As an ygg user
4
+ I want to manage an event log
5
+
6
+ Background: Setting up the enviroment
7
+ Given I have the base path "emulations/samples"
8
+ And the class User has the field :name
9
+
10
+ Scenario: Accessing the last event
11
+ Given the file "emulations/samples/event.ygg" contains:
12
+ """
13
+ - !ruby/object:YggDemo::User
14
+ name: John Doe
15
+ """
16
+ When I interact with the resource :event
17
+ Then I should see that the last event loaded some User
@@ -0,0 +1,40 @@
1
+ Feature: Load and save a simple record from a file
2
+ In order to check Ygg's ability to manage record
3
+ As a Ygg developer
4
+ I want to load and save simple YAML records
5
+
6
+ Scenario: Load a basic User record
7
+ Given the class User has the field :name
8
+ And the file "emulations/samples/user.ygg" contains:
9
+ """
10
+ - !ruby/object:YggDemo::User
11
+ name: Xavier Via
12
+ """
13
+ When I load the file and get the records
14
+ Then the first record should be a User
15
+ And it should have the name "Xavier Via"
16
+
17
+ @saves
18
+ Scenario: Save a basic User record
19
+ Given the class User has the field :name
20
+ And I have a user "Catalina" in an array
21
+ When I load the file "emulations/samples/saving.ygg" and add the array to the data
22
+ Then the file should contain:
23
+ """
24
+ - !ruby/object:YggDemo::User
25
+ name: Catalina
26
+ """
27
+
28
+ Scenario: Set a base folder and load files with symbols
29
+ Given I have the file "emulations/samples/user.ygg"
30
+ When I set "emulations/samples" as base folder
31
+ And I load :user
32
+ Then I should get non empty data
33
+
34
+ Scenario: No block given, no data saved
35
+ Given the class User has the field :name
36
+ And I have the file "emulations/samples/user.ygg"
37
+ And I get its modified date
38
+ When I load it without block
39
+ Then I should get non empty data
40
+ And the file should not have been modified
@@ -0,0 +1,8 @@
1
+ Given /^extends Record$/ do
2
+ @the_class.extend Ygg::Record
3
+ end
4
+
5
+ When /^I load the file and ask (.+?) for records$/ do |type|
6
+ @the_class = YggDemo.const_get type
7
+ @the_records = @the_class.from_ygg
8
+ end
@@ -0,0 +1,20 @@
1
+ Given /^the path "(.+?)"$/ do |path|
2
+ @argument_path = File.dirname(File.dirname(File.dirname(__FILE__)))
3
+ @argument_path += "/#{path}"
4
+ end
5
+
6
+ Given /^the identifier :(.+?)$/ do |identifier_name|
7
+ @the_identifier = identifier_name.to_sym
8
+ end
9
+
10
+ When /^I call ygg with those arguments$/ do
11
+ ygg @argument_path, @the_identifier
12
+ end
13
+
14
+ When /^I load the file$/ do
15
+ ygg @the_path
16
+ end
17
+
18
+ When /^I ask (.+?) for records$/ do |type|
19
+ @the_records = YggDemo.const_get(type).from_ygg
20
+ end
@@ -0,0 +1,12 @@
1
+ Given /^I have the base path "(.+?)"$/ do |path|
2
+ Ygg.base_dir = File.dirname(File.dirname(File.dirname(__FILE__))) +
3
+ "/#{path}"
4
+ end
5
+
6
+ When /^I interact with the resource :(.+?)$/ do |resource_name|
7
+ ygg resource_name.to_sym
8
+ end
9
+
10
+ Then /^I should see that the last event loaded some (.+?)$/ do |what|
11
+ ygg.events.last.should have_loaded_some(YggDemo.const_get(what))
12
+ end
@@ -0,0 +1,104 @@
1
+ module YggDemo
2
+ end
3
+
4
+ # Given
5
+ Given /the class (.+?) has the field :(.+?)$/ do |class_name, field_name|
6
+ if YggDemo.const_defined? class_name
7
+ @the_class = YggDemo.const_get class_name
8
+ else
9
+ @the_class = YggDemo.const_set class_name, Class.new
10
+ end
11
+
12
+ @the_class.send :attr_accessor, field_name.to_sym
13
+ end
14
+
15
+ Given /the file "(.+?)" contains:/ do |path, content|
16
+ base_path = File.dirname(File.dirname(File.dirname(__FILE__)))
17
+ @the_path = "#{base_path}/#{path}"
18
+ @the_content = File.read @the_path
19
+ @the_content.should include(content)
20
+ end
21
+
22
+ Given /I have a user "(.+?)"/ do |user_name|
23
+ @the_user = YggDemo::User.new
24
+ @the_user.name = user_name
25
+ end
26
+
27
+ Given /^I have the file "(.+?)"$/ do |path|
28
+ base_path = File.dirname(File.dirname(File.dirname(__FILE__)))
29
+ @the_path = "#{base_path}/#{path}"
30
+ File.should exist(@the_path)
31
+ end
32
+
33
+ Given /^I get its modified date$/ do
34
+ @last_modification_time = File.new(@the_path).mtime
35
+ end
36
+
37
+ # When
38
+ When /I load the file and get the records/ do
39
+ @the_records = nil
40
+ ygg @the_path do
41
+ @the_records = records
42
+ end
43
+ end
44
+
45
+ When /^I load the file and request for objects of type (.+?)$/ do |type|
46
+ @the_records = nil
47
+ ygg @the_path do
48
+ @the_records = records.of_type YggDemo.const_get(type)
49
+ end
50
+ end
51
+
52
+ When /I load the file "(.+?)" and add the array to the data$/ do |file_name|
53
+ base_path = File.dirname(File.dirname(File.dirname(__FILE__)))
54
+ @the_path = "#{base_path}/#{file_name}"
55
+ ygg @the_path do
56
+ add @the_user
57
+ end
58
+ end
59
+
60
+ When /I set "(.+?)" as base folder/ do |path|
61
+ base_path = File.dirname(File.dirname(File.dirname(__FILE__)))
62
+ @base_dir = "#{base_path}/#{path}"
63
+ Ygg.base_dir = @base_dir
64
+ end
65
+
66
+ When /^I load :([a-z]+?)$/ do |file|
67
+ @the_data = nil
68
+ ygg file.to_sym do
69
+ @the_data = records
70
+ end
71
+ end
72
+
73
+ When /^I load it without block$/ do
74
+ @the_data = ygg @the_path
75
+ end
76
+
77
+ # Them
78
+ Then /the first record should be a (.+?)$/ do |type|
79
+ @first_record = @the_records.first
80
+ @first_record.should be_a(YggDemo.const_get(type))
81
+ end
82
+
83
+ Then /it should have the (.+?) "(.+?)"/ do |field_name, value|
84
+ @first_record.send(field_name.to_sym).should == value
85
+ end
86
+
87
+ Then /the file should contain:/ do |content|
88
+ File.should exist(@the_path)
89
+ @the_content = File.read @the_path
90
+ @the_content.should include(content)
91
+ end
92
+
93
+ Then /^I should get non empty data$/ do
94
+ @the_data.should_not be_empty
95
+ end
96
+
97
+ Then /^the file should not have been modified$/ do
98
+ @current_modification_time = File.new(@the_path).mtime
99
+ @current_modification_time.should == @last_modification_time
100
+ end
101
+
102
+ Then /^I should get an user named "(.+?)"$/ do |user_name|
103
+ @the_records.first.name.should == user_name
104
+ end
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH << File.expand_path("../../../lib", __FILE__)
2
+ require "ygg"
@@ -0,0 +1,3 @@
1
+ After "@saves" do
2
+ File.unlink @the_path
3
+ end
data/lib/ygg.rb CHANGED
@@ -1,5 +1,99 @@
1
- require "ygg/base"
1
+ require "yaml"
2
+ require "metafun/delegator"
2
3
 
3
- include Ygg::Delegator
4
+ # Its time to start over. Bit by bit. Comment everything until
5
+ # features and specs are supplied
4
6
 
5
- delegate Ygg, :save, :data, :load
7
+ require "ygg/databundle"
8
+ require "ygg/session"
9
+ require "ygg/record"
10
+ require "ygg/exceptions"
11
+
12
+ module Ygg
13
+ def self.reset
14
+ @@base_dir = "."
15
+ @@sessions = []
16
+ end
17
+
18
+ reset
19
+
20
+ def self.path_to( source )
21
+ if source.is_a? Symbol
22
+ return "#{@@base_dir}/#{source}.ygg"
23
+ else
24
+ return source
25
+ end
26
+ end
27
+
28
+ def self.transaction( source, &block )
29
+ if not block and not File.exist?(path_to(source))
30
+ raise UnavailableResourceException,
31
+ "No resource was found in #{path_to(source)}"
32
+ end
33
+
34
+ @@sessions << Session.new(path_to(source))
35
+
36
+ if block
37
+ @@within_block = true
38
+ yield block
39
+ @@within_block = nil
40
+ @@sessions.last.shutdown
41
+ end
42
+ return @@sessions.last.records
43
+ end
44
+
45
+ def self.ygg(*args, &block)
46
+ return Ygg if args.empty?
47
+
48
+ self.base_dir = args.shift if args.length > 1
49
+ source = args.shift
50
+
51
+ transaction(source, &block)
52
+ end
53
+
54
+ def self.add(*resources)
55
+ raise ArgumentError if resources.empty?
56
+
57
+ begin
58
+ event = events.last
59
+ resources.each do |resource|
60
+ event.records << resource
61
+ end
62
+ rescue NoInteractionDoneException => e
63
+ raise UnavailableResourceException, "No resource was loaded, impossible to add the object"
64
+ end
65
+ end
66
+
67
+ def self.records
68
+ events.last.records
69
+ end
70
+
71
+ def self.base_dir=(dir)
72
+ @@base_dir = dir
73
+ end
74
+
75
+ def self.base_dir
76
+ @@base_dir
77
+ end
78
+
79
+ def self.events
80
+ raise NoInteractionDoneException, "No events to load in the log." if @@sessions.empty?
81
+ @@sessions
82
+ end
83
+
84
+ def self.resource(*args)
85
+ if args.empty?
86
+ raise OutOfBlockException, "The resource is not available outside an ygg block." unless @@within_block
87
+ events.last
88
+ else
89
+ case args[0]
90
+ when :path
91
+ events.last.source
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ extend Metafun::Delegator
98
+
99
+ delegate Ygg, :ygg, :records, :add
@@ -0,0 +1,63 @@
1
+ module Ygg
2
+ DEFAULT_SOURCE = "your_tree.ygg"
3
+
4
+ class Base
5
+ @@source = Ygg::DEFAULT_SOURCE
6
+ @@data = {}
7
+
8
+ def self.load(source, &block)
9
+ Base.assign_source source if source
10
+ Base.assign_data if File.exists? @@source
11
+
12
+ if block; yield; self.save; self.close; end
13
+ end
14
+
15
+ def self.assign_source(source)
16
+ if source.is_a? Symbol then @@source = "#{source}.ygg"
17
+ else @@source = source
18
+ end
19
+
20
+ def self.assign_data
21
+ @@data = YAML.load_file @@source
22
+
23
+ # Clarify!
24
+ @@data.each do |key, model|
25
+ model.each do |resource|
26
+ resource.loading! if resource.respond_to? :loading!
27
+ end if model.kind_of? Array
28
+ end
29
+ end
30
+
31
+ def self.save
32
+ Base.finalize
33
+
34
+ Base.write
35
+ end
36
+
37
+ def self.finalize
38
+ @@data.each do |key, model|
39
+ model.each do |resource|
40
+ resource._finalize! if resource.respond_to? :_finalize!
41
+ end if model.kind_of? Array
42
+ end
43
+ end
44
+
45
+ def self.data
46
+ @@data
47
+ end
48
+
49
+ def self.close
50
+ @@data = nil
51
+ end
52
+
53
+ def self.write
54
+ File.open @@source, "w" do |file|
55
+ file.write YAML.dump(@@data)
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.ygg(source = nil, &block)
61
+ Base.load source, block
62
+ end
63
+ end
@@ -0,0 +1,31 @@
1
+ module Ygg
2
+ class Branch < Array
3
+ def method_missing(x, *args)
4
+ if matches = x.to_s.match(/^sort_by_(.+)$/)
5
+ key = matches[1].to_sym
6
+ self.sort_by { |x| x.send(key) }
7
+
8
+ elsif matches = x.to_s.match(/^by_(.+)$/) # Extend with regexps
9
+ key = matches[1].to_sym
10
+
11
+ if to_find = args.shift
12
+ result = Branch.new
13
+ self.each do |res|
14
+ if res.respond_to? key
15
+ datus = res.send key
16
+ result << res if datus == to_find
17
+ end
18
+ end
19
+ return Branch.new if result.length == 0
20
+ return result[0] if result.length == 1
21
+ return result
22
+
23
+ else
24
+ self.send(:"sort_by_#{key}")[0] unless empty?
25
+ end
26
+
27
+ return Branch.new
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Ygg
2
+ class InvalidInitializor < RuntimeError; end
3
+ end