gexp 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/gexp.gemspec +32 -0
- data/lib/gexp.rb +16 -0
- data/lib/gexp/command.rb +50 -0
- data/lib/gexp/command/object.rb +37 -0
- data/lib/gexp/command/stack.rb +50 -0
- data/lib/gexp/handler.rb +25 -0
- data/lib/gexp/handler/caller.rb +8 -0
- data/lib/gexp/handler/check.rb +9 -0
- data/lib/gexp/handler/check/item.rb +34 -0
- data/lib/gexp/handler/check/resources.rb +56 -0
- data/lib/gexp/handler/modify.rb +9 -0
- data/lib/gexp/handler/modify/resources.rb +81 -0
- data/lib/gexp/handler/producer.rb +61 -0
- data/lib/gexp/handler/transition.rb +44 -0
- data/lib/gexp/handler/transition/builder.rb +33 -0
- data/lib/gexp/mongoid.rb +4 -0
- data/lib/gexp/mongoid/transaction.rb +266 -0
- data/lib/gexp/object.rb +39 -0
- data/lib/gexp/receiver.rb +33 -0
- data/lib/gexp/state_definition.rb +4 -0
- data/lib/gexp/state_definition/state_machine.rb +90 -0
- data/lib/gexp/version.rb +3 -0
- data/spec/gexp/command/object_spec.rb +84 -0
- data/spec/gexp/command/stack_spec.rb +74 -0
- data/spec/gexp/command_spec.rb +59 -0
- data/spec/gexp/handler/check/item_spec.rb +45 -0
- data/spec/gexp/handler/check/resources_spec.rb +81 -0
- data/spec/gexp/handler/check_spec.rb +5 -0
- data/spec/gexp/handler/modify/resources_spec.rb +96 -0
- data/spec/gexp/handler/modify_spec.rb +6 -0
- data/spec/gexp/handler/producer_spec.rb +85 -0
- data/spec/gexp/handler/transition/builder_spec.rb +122 -0
- data/spec/gexp/handler/transition_spec.rb +14 -0
- data/spec/gexp/mongoid/transaction_spec.rb +210 -0
- data/spec/gexp/state_definition/state_machine_spec.rb +48 -0
- data/spec/spec_helper.rb +10 -0
- metadata +210 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
|
data/lib/gexp/command.rb
ADDED
@@ -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
|
data/lib/gexp/handler.rb
ADDED
@@ -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,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,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
|