gexp 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE.txt +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +1 -0
  6. data/gexp.gemspec +32 -0
  7. data/lib/gexp.rb +16 -0
  8. data/lib/gexp/command.rb +50 -0
  9. data/lib/gexp/command/object.rb +37 -0
  10. data/lib/gexp/command/stack.rb +50 -0
  11. data/lib/gexp/handler.rb +25 -0
  12. data/lib/gexp/handler/caller.rb +8 -0
  13. data/lib/gexp/handler/check.rb +9 -0
  14. data/lib/gexp/handler/check/item.rb +34 -0
  15. data/lib/gexp/handler/check/resources.rb +56 -0
  16. data/lib/gexp/handler/modify.rb +9 -0
  17. data/lib/gexp/handler/modify/resources.rb +81 -0
  18. data/lib/gexp/handler/producer.rb +61 -0
  19. data/lib/gexp/handler/transition.rb +44 -0
  20. data/lib/gexp/handler/transition/builder.rb +33 -0
  21. data/lib/gexp/mongoid.rb +4 -0
  22. data/lib/gexp/mongoid/transaction.rb +266 -0
  23. data/lib/gexp/object.rb +39 -0
  24. data/lib/gexp/receiver.rb +33 -0
  25. data/lib/gexp/state_definition.rb +4 -0
  26. data/lib/gexp/state_definition/state_machine.rb +90 -0
  27. data/lib/gexp/version.rb +3 -0
  28. data/spec/gexp/command/object_spec.rb +84 -0
  29. data/spec/gexp/command/stack_spec.rb +74 -0
  30. data/spec/gexp/command_spec.rb +59 -0
  31. data/spec/gexp/handler/check/item_spec.rb +45 -0
  32. data/spec/gexp/handler/check/resources_spec.rb +81 -0
  33. data/spec/gexp/handler/check_spec.rb +5 -0
  34. data/spec/gexp/handler/modify/resources_spec.rb +96 -0
  35. data/spec/gexp/handler/modify_spec.rb +6 -0
  36. data/spec/gexp/handler/producer_spec.rb +85 -0
  37. data/spec/gexp/handler/transition/builder_spec.rb +122 -0
  38. data/spec/gexp/handler/transition_spec.rb +14 -0
  39. data/spec/gexp/mongoid/transaction_spec.rb +210 -0
  40. data/spec/gexp/state_definition/state_machine_spec.rb +48 -0
  41. data/spec/spec_helper.rb +10 -0
  42. metadata +210 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gexp.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Kazantsev Nickolay
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Gexp
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'gexp'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install gexp
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/gexp.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'gexp/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "gexp"
8
+ gem.version = Gexp::VERSION
9
+ gem.authors = ["Kazantsev Nickolay"]
10
+ gem.email = ["kazantsev.nickolay@gmail.com"]
11
+ gem.description = %q{Gexp - comand hadlers}
12
+ gem.summary = %q{Gexp - comand hadlers}
13
+ gem.homepage = "http://github.com/realb0t/gexp"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.rubyforge_project = "gexp"
21
+
22
+ gem.add_development_dependency "rspec"
23
+ gem.add_development_dependency "rr"
24
+ gem.add_development_dependency "rake"
25
+ gem.add_development_dependency "state_machine"
26
+ gem.add_development_dependency "activesupport"
27
+ gem.add_development_dependency 'bson', '= 1.8.0'
28
+ gem.add_development_dependency 'bson_ext', '= 1.8.0'
29
+ gem.add_development_dependency 'mongo', '~> 1.8.0'
30
+ gem.add_development_dependency "mongoid", "~> 3.0.0"
31
+ gem.add_development_dependency 'money-mongoid', '= 0.1.2'
32
+ end
data/lib/gexp.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "gexp/version"
2
+
3
+ module Gexp
4
+ class << self
5
+ def label_to_class(label)
6
+ label.split('.').
7
+ map(&:classify).
8
+ join('::').constantize
9
+ end
10
+
11
+ def class_to_label(klass)
12
+ klass.name.split('::').
13
+ map(&:underscore).join('.')
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ module Gexp
3
+ class Command
4
+
5
+ attr_accessor :errors
6
+ attr_accessor :context
7
+ attr_accessor :params
8
+
9
+ state_machine :initial => :new do
10
+ state :active
11
+ state :done
12
+ state :failed
13
+
14
+ event :activate do
15
+ transition :new => :active
16
+ end
17
+
18
+ event :complete do
19
+ transition :active => :done
20
+ end
21
+
22
+ event :failure do
23
+ transition :active => :failed
24
+ end
25
+ end
26
+
27
+ def initialize(params = {})
28
+ @params = params.dup
29
+ @errors = []
30
+
31
+ super() # Инициализация StateMachine
32
+ end
33
+
34
+ def hash
35
+ # TODO: Заменить на BSON:ObjectId
36
+ [
37
+ @params[:timestamp],
38
+ @params[:event],
39
+ @params[:seed],
40
+ ].join('_')
41
+ end
42
+
43
+ def perform
44
+ self.activate!
45
+ self.failure!
46
+ raise 'Not defined perform method'
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ module Gexp
2
+ class Command
3
+ class Object < self
4
+
5
+ attr_accessor :event # TODO: only getter
6
+ attr_accessor :object
7
+
8
+ def initialize(params = {})
9
+ super
10
+ @event = @params[:event]
11
+ self.load_object
12
+ end
13
+
14
+ def perform
15
+ self.activate!
16
+ @object.send(self.event)
17
+ self.complete!
18
+ rescue => e
19
+ self.errors << e
20
+ self.failure!
21
+ end
22
+
23
+ protected
24
+
25
+ def load_object
26
+ if @params[:object]
27
+ label = @params[:object].keys.first
28
+ id = @params[:object].values.first
29
+ @object = Gexp.label_to_class(label).find(id)
30
+ else
31
+ raise "Can't find object params"
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ module Gexp
2
+ class Command
3
+ class Stack
4
+
5
+ include Enumerable
6
+
7
+ attr_accessor :user, :request
8
+
9
+ def initialize(user, request)
10
+ @user = user
11
+ @request = request
12
+ @commands = {} # for ruby 1.9.x
13
+ self.fill()
14
+ end
15
+
16
+ def build_command(command_param = {})
17
+ Gexp::Command.new(command_param)
18
+ end
19
+
20
+ def fill(request = nil)
21
+ request ||= @request
22
+ @commands = {}
23
+
24
+ opts = request[:params][:commands] || []
25
+ opts.each do |command_param|
26
+ self.add self.build_command(command_param)
27
+ end
28
+ end
29
+
30
+ def size
31
+ @commands.size
32
+ end
33
+
34
+ def each(&block)
35
+ @commands.each(&block)
36
+ end
37
+
38
+ protected
39
+
40
+ def add(command)
41
+ command.context = self
42
+ if @commands[command.hash].present?
43
+ raise "Command with hash #{command.hash} be exist"
44
+ end
45
+ @commands[command.hash] = command
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,25 @@
1
+ module Gexp
2
+ class Handler
3
+ # Базовый класс обработчиков
4
+
5
+ attr_accessor :user, :object
6
+
7
+ #
8
+ #
9
+ # object - объект над котым производится обработка
10
+ #
11
+ #
12
+ def initialize(object = nil, params = {}, objects = nil, full_params = nil)
13
+ @object = object
14
+ @params = params
15
+ @objects = objects
16
+ @user = (@objects || {})[:self]
17
+ @full_params = full_params
18
+ end
19
+
20
+ def process(params = nil)
21
+ raise 'Override process handler method'
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,8 @@
1
+ module Gexp
2
+ class Handler
3
+ class Caller < self
4
+
5
+
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Gexp
2
+ class Handler
3
+ class Check < self
4
+ def process
5
+ true
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,34 @@
1
+ module Gexp
2
+ class Handler
3
+ class Check
4
+ class Item < self
5
+
6
+ def process(params, &block)
7
+
8
+ results = params.map do |key, value|
9
+ [
10
+ key,
11
+ value,
12
+ @user.have_with_type?(key.to_s, value),
13
+ ]
14
+ end
15
+
16
+ haves = results.map(&:last).all?
17
+
18
+ if block_given?
19
+ return block.call(results) if haves
20
+ else
21
+ unless haves
22
+ view = results.map { |r| "#{r.first}_#{r.second}" }
23
+ raise Exception.new("not_have_items-#{view.join(',')}")
24
+ end
25
+
26
+ haves
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,56 @@
1
+ module Gexp
2
+ class Handler
3
+ class Check
4
+ class Resources < self
5
+
6
+ def chain_resource(resource, object = nil, params = nil)
7
+ if resource.is_a?(Array) # Если цепочка как массив
8
+ curr_field = resource.shift
9
+ if object # Если уже был получен результат
10
+ if resource.count.zero? # Если последний метод в цепочке
11
+ if params
12
+ # Если сеттер
13
+ object.send(curr_field, params) # last
14
+ else
15
+ # Если геттер
16
+ object.send(curr_field)
17
+ end
18
+ else # Если не последний метод в цепочке
19
+ access_resource_get(resource, object.send(curr_field), params)
20
+ end
21
+ else # Если метод еще не было вызовов
22
+ access_resource_get(resource, @user.send(curr_field), params)
23
+ end
24
+ else # Если цепочка как строка
25
+ access_resource_get(resource.split('.'), object, params)
26
+ end
27
+ end
28
+
29
+ def process(params, &block)
30
+
31
+ compairs = params.map do |resource, value|
32
+ if @user.respond_to?(resource)
33
+ current = @user.send(resource.to_s.split('.').last)
34
+ [ current >= value, current, value, resource ]
35
+ end
36
+ end
37
+
38
+ compairs.compact!
39
+ results = compairs.map(&:first).all?
40
+
41
+ if block_given?
42
+ block.call(compairs) if results
43
+ else
44
+ unless results
45
+ resources = compairs.reject(&:first).map(&:fourth)
46
+ raise Exception.new("out_of_resources-#{resources.join(',')}")
47
+ end
48
+
49
+ results
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ module Gexp
2
+ class Handler
3
+ class Modify < self
4
+ def process
5
+ @user
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+
3
+ # Изменяет количество ресурсов у пользователя
4
+ module Gexp
5
+ class Handler
6
+ class Modify
7
+ class Resources < self
8
+
9
+ class Exception < StandardError; end
10
+
11
+ # Нормализация энергии
12
+ def normalize_energy(value)
13
+ if value > @user.max_energy
14
+ @user.max_energy
15
+ else
16
+ value
17
+ end
18
+ end
19
+
20
+ # Нормализация неопределенного ресурса
21
+ def normalize_undefined(value)
22
+ value
23
+ end
24
+
25
+ # Нормальлизация значений ресурсов
26
+ def normalize(resource, value)
27
+ return 0 if value < 0
28
+ method_name = "normalize_#{resource}"
29
+
30
+ if self.respond_to?(method_name)
31
+ self.send(method_name, value)
32
+ else
33
+ self.normalize_undefined value
34
+ end
35
+ end
36
+
37
+ # Применение изменений к ОВ
38
+ def apply_changes
39
+ @changes.each do |resource, value|
40
+ @user.send("#{resource}=", value[:after])
41
+ end
42
+ end
43
+
44
+ # Применимы изменения к объекту в момент обработки
45
+ def ontime_apply?
46
+ true # TODO: сделать выяснения что изменения применимы
47
+ end
48
+
49
+ def process(params = {}, &block)
50
+ @changes = {}
51
+ @params = params if @params.empty?
52
+ @params.each do |resource, value|
53
+ if @user.respond_to?(resource.to_sym)
54
+
55
+ if @user.send(resource) + value < 0
56
+ raise Exception.new("out_of_resource-#{resource}")
57
+ end
58
+
59
+ before_value = @user.send(resource)
60
+ new_value = before_value + value
61
+ norm_value = self.normalize(resource, new_value)
62
+
63
+ @changes[resource] = {
64
+ before: before_value,
65
+ delta: value,
66
+ after: norm_value,
67
+ }
68
+ end
69
+ end
70
+
71
+ self.apply_changes if self.ontime_apply?
72
+ @user.after_change!(@changes)
73
+
74
+ return block.call(@user) if block_given?
75
+ @user
76
+ end
77
+
78
+ end
79
+ end
80
+ end
81
+ end