railjet 1.0.1
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 +7 -0
- data/.gitignore +44 -0
- data/.rspec +2 -0
- data/.ruby-gemset +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +2 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +96 -0
- data/LICENSE.txt +21 -0
- data/README.md +250 -0
- data/Rakefile +17 -0
- data/VERSION +1 -0
- data/bin/bundler +17 -0
- data/bin/coderay +17 -0
- data/bin/console +14 -0
- data/bin/htmldiff +17 -0
- data/bin/ldiff +17 -0
- data/bin/pry +17 -0
- data/bin/rake +17 -0
- data/bin/rspec +17 -0
- data/bin/setup +8 -0
- data/lib/active_model/merge_errors.rb +22 -0
- data/lib/gettext_i18n/translate_attributes.rb +73 -0
- data/lib/railjet.rb +46 -0
- data/lib/railjet/auth/ability.rb +20 -0
- data/lib/railjet/auth/activity.rb +12 -0
- data/lib/railjet/composed_policy.rb +41 -0
- data/lib/railjet/context.rb +32 -0
- data/lib/railjet/form.rb +10 -0
- data/lib/railjet/policy.rb +26 -0
- data/lib/railjet/railtie.rb +7 -0
- data/lib/railjet/repository.rb +34 -0
- data/lib/railjet/repository/active_record.rb +54 -0
- data/lib/railjet/repository/cupido.rb +34 -0
- data/lib/railjet/repository/registry.rb +71 -0
- data/lib/railjet/use_case.rb +65 -0
- data/lib/railjet/util/form_helper.rb +26 -0
- data/lib/railjet/util/policy_helper.rb +9 -0
- data/lib/railjet/util/use_case_helper.rb +9 -0
- data/lib/railjet/validator.rb +15 -0
- data/lib/railjet/version.rb +3 -0
- data/lib/tasks/gettext_i18n.rake +36 -0
- data/railjet.gemspec +33 -0
- metadata +226 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module Railjet
|
2
|
+
module Policy
|
3
|
+
extend ::ActiveSupport::Concern
|
4
|
+
include Railjet::Validator
|
5
|
+
|
6
|
+
attr_reader :context, :object
|
7
|
+
|
8
|
+
def initialize(context, object)
|
9
|
+
@context, @object = context, object
|
10
|
+
end
|
11
|
+
|
12
|
+
def validate!
|
13
|
+
valid? || (raise Railjet::PolicyError.new(errors) )
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def context(*context_members)
|
18
|
+
delegate *context_members, to: :context
|
19
|
+
end
|
20
|
+
|
21
|
+
def object(name)
|
22
|
+
alias_method name, :object
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require "railjet/repository/active_record"
|
2
|
+
require "railjet/repository/cupido"
|
3
|
+
|
4
|
+
module Railjet
|
5
|
+
module Repository
|
6
|
+
extend ::ActiveSupport::Concern
|
7
|
+
|
8
|
+
attr_reader :registry
|
9
|
+
delegate :settings, to: :registry
|
10
|
+
|
11
|
+
attr_reader :record_dao, :cupido_dao
|
12
|
+
|
13
|
+
def initialize(registry, record: nil, cupido: nil)
|
14
|
+
@registry = registry
|
15
|
+
|
16
|
+
@record_dao = record
|
17
|
+
@cupido_dao = cupido
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def record
|
23
|
+
if self.class.const_defined?("ActiveRecordRepository")
|
24
|
+
@record ||= self.class::ActiveRecordRepository.new(registry, record_dao)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def cupido
|
29
|
+
if self.class.const_defined?("CupidoRepository")
|
30
|
+
@cupido ||= self.class::CupidoRepository.new(registry, cupido_dao)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Railjet
|
2
|
+
module Repository
|
3
|
+
module ActiveRecord
|
4
|
+
extend ::ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
attr_reader :registry, :record
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(registry, record = nil)
|
11
|
+
@registry = registry
|
12
|
+
@record = record
|
13
|
+
end
|
14
|
+
|
15
|
+
def all
|
16
|
+
record.all
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_by_ids(ids)
|
20
|
+
record.where(id: ids)
|
21
|
+
end
|
22
|
+
|
23
|
+
def build(args = {}, &block)
|
24
|
+
record.new(args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def duplicate(object, args = {})
|
28
|
+
object.dup.tap do |new_object|
|
29
|
+
new_object.assign_attributes(args) if args.present?
|
30
|
+
yield(new_object) if block_given?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def persist(object)
|
35
|
+
object.save!
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy(object)
|
39
|
+
object.destroy!
|
40
|
+
end
|
41
|
+
|
42
|
+
def transaction(&block)
|
43
|
+
record.transaction(&block)
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def query_columns
|
49
|
+
columns = (record.column_names - [:created_at, :updated_at])
|
50
|
+
columns.map { |column_name| "#{record.table_name}.#{column_name}" }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Railjet
|
2
|
+
module Repository
|
3
|
+
module Cupido
|
4
|
+
extend ::ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
attr_reader :registry, :cupido
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(registry, cupido = nil)
|
11
|
+
@registry = registry
|
12
|
+
@cupido = cupido
|
13
|
+
end
|
14
|
+
|
15
|
+
def build(args = {})
|
16
|
+
cupido.new(args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def persist(object)
|
20
|
+
cupido.do.create(object)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def for_person(person)
|
26
|
+
cupido.find.proxy(person.external_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def cupido_class(obj)
|
30
|
+
"Cupido::#{obj.class.name}".constantize
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Railjet
|
2
|
+
module Repository
|
3
|
+
class Registry
|
4
|
+
attr_reader :repositories, :initialized_repositories
|
5
|
+
protected :repositories, :initialized_repositories
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@repositories = {}
|
9
|
+
@initialized_repositories = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def register(name, repository, **kwargs)
|
13
|
+
add_to_registry(name, repository, kwargs)
|
14
|
+
define_accessor(name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def new(**kwargs)
|
18
|
+
self.clone.tap do |registry|
|
19
|
+
unless kwargs.blank?
|
20
|
+
clone_module = Module.new.tap { |m| registry.extend(m) }
|
21
|
+
|
22
|
+
kwargs.each do |name, val|
|
23
|
+
clone_module.send(:define_method, name) { val }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def initialize_copy(original)
|
32
|
+
super
|
33
|
+
|
34
|
+
@initialized_repositories = original.initialized_repositories.dup
|
35
|
+
@repositories = original.repositories.dup
|
36
|
+
@registry_module = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_to_registry(name, repository, args = {})
|
40
|
+
initialized_repositories[name] = nil
|
41
|
+
repositories[name] = {
|
42
|
+
repository: repository,
|
43
|
+
args: args
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_from_registry(name)
|
48
|
+
repositories[name]
|
49
|
+
end
|
50
|
+
|
51
|
+
def initialize_repo(name)
|
52
|
+
initialized_repositories[name] ||= begin
|
53
|
+
repo = get_from_registry(name)
|
54
|
+
klass = repo[:repository]
|
55
|
+
args = repo[:args]
|
56
|
+
|
57
|
+
klass.new(self, **args)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def define_accessor(name)
|
62
|
+
pluralized_name = name.to_s.pluralize
|
63
|
+
registry_module.send(:define_method, pluralized_name) { initialize_repo(name) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def registry_module
|
67
|
+
@registry_module ||= Module.new.tap { |m| self.class.include(m) }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Railjet
|
2
|
+
module UseCase
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
include ::Railjet::Util::UseCaseHelper
|
5
|
+
include ::Railjet::Util::PolicyHelper
|
6
|
+
|
7
|
+
attr_reader :context
|
8
|
+
|
9
|
+
def initialize(context)
|
10
|
+
@context = context
|
11
|
+
end
|
12
|
+
|
13
|
+
def with_requirements_check(*args)
|
14
|
+
with_ability_check(*args) do
|
15
|
+
with_policy_check(*args) do
|
16
|
+
yield if block_given?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def with_ability_check(*args)
|
22
|
+
if check_ability!(*args)
|
23
|
+
yield if block_given?
|
24
|
+
else
|
25
|
+
raise Railjet::UnauthorizedError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_policy_check(*args)
|
30
|
+
check_policy!(*args)
|
31
|
+
yield if block_given?
|
32
|
+
rescue Railjet::PolicyError => e
|
33
|
+
raise Railjet::PolicyNotMetError.new(e.errors)
|
34
|
+
end
|
35
|
+
|
36
|
+
def check_ability!(*args)
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_policy!(*args)
|
41
|
+
true
|
42
|
+
end
|
43
|
+
|
44
|
+
module ClassMethods
|
45
|
+
def context(*context_members)
|
46
|
+
delegate *context_members, to: :context
|
47
|
+
end
|
48
|
+
|
49
|
+
def repositories(*repositories)
|
50
|
+
context :repository
|
51
|
+
delegate *repositories, to: :repository
|
52
|
+
end
|
53
|
+
|
54
|
+
def check_ability(ability_name)
|
55
|
+
define_method :check_ability! do |*args|
|
56
|
+
context.current_ability.send(ability_name, *args)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def check_policy(&block)
|
61
|
+
define_method :check_policy!, &block
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Railjet
|
2
|
+
module Util
|
3
|
+
module FormHelper
|
4
|
+
def form(klass)
|
5
|
+
klass.new(clean_params).tap(&:validate!)
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def object_params
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
def clean_params
|
15
|
+
object_params
|
16
|
+
end
|
17
|
+
|
18
|
+
def respond_with_errors(object_with_errors, status: :unprocessable_entity)
|
19
|
+
raise ArgumentError unless object_with_errors.respond_to?(:errors)
|
20
|
+
|
21
|
+
response = object_with_errors.errors.to_hash(true)
|
22
|
+
render json: response, status: status
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Railjet
|
2
|
+
# @private Use either form or policy
|
3
|
+
module Validator
|
4
|
+
extend ::ActiveSupport::Concern
|
5
|
+
include ::ActiveModel::Model
|
6
|
+
|
7
|
+
included do
|
8
|
+
include Virtus.model(nullify_blank: true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate!
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
namespace :gettext do
|
2
|
+
def files_to_translate
|
3
|
+
Dir.glob("{app,lib,config,locale,gems,engines}/**/*.{rb,erb,haml,slim,rhtml}")
|
4
|
+
end
|
5
|
+
|
6
|
+
desc "write the form attributes to <locale_path>/form_attributes.rb"
|
7
|
+
task :store_form_attributes, [:file] => :environment do |t, args|
|
8
|
+
FastGettext.silence_errors
|
9
|
+
|
10
|
+
require "gettext_i18n/translate_attributes"
|
11
|
+
|
12
|
+
storage_file = args[:file] || "#{locale_path}/form_attributes.rb"
|
13
|
+
puts "writing form translations to: #{storage_file}"
|
14
|
+
|
15
|
+
GettextI18n::TranslateAttributes.store_form_attributes(file: storage_file)
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "write the policy attributes to <locale_path>/policy_attributes.rb"
|
19
|
+
task :store_policy_attributes, [:file] => :environment do |t, args|
|
20
|
+
args.with_defau
|
21
|
+
FastGettext.silence_errors
|
22
|
+
|
23
|
+
require "gettext_i18n/translate_attributes"
|
24
|
+
|
25
|
+
storage_file = args[:file] || "#{locale_path}/policy_attributes.rb"
|
26
|
+
puts "writing form translations to: #{storage_file}"
|
27
|
+
|
28
|
+
GettextI18n::TranslateAttributes.store_policy_attributes(file: storage_file)
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "write validators (policy & form) attributes"
|
32
|
+
task :store_attributes, [:form_file, :policy_file] => :environment do |t, args|
|
33
|
+
Rake::Task["gettext:store_form_attributes", args[:form_file]].invoke
|
34
|
+
Rake::Task["gettext:store_policy_attributes", args[:policy_file]].invoke
|
35
|
+
end
|
36
|
+
end
|
data/railjet.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "railjet/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "railjet"
|
8
|
+
spec.version = Railjet::VERSION
|
9
|
+
spec.authors = ["Krzysztof Zalewski"]
|
10
|
+
spec.email = ["zlw.zalewski@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Better architecture for high-speed railway}
|
13
|
+
spec.description = %q{Design patterns for Ruby on Rails}
|
14
|
+
spec.homepage = "https://github.com/nedap/railjet"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.11"
|
23
|
+
spec.add_development_dependency "rake", "~> 11.0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
25
|
+
spec.add_development_dependency "pry"
|
26
|
+
spec.add_development_dependency "gemfury"
|
27
|
+
spec.add_development_dependency "rake-version", "~> 1.0"
|
28
|
+
|
29
|
+
spec.add_dependency "activesupport", '~> 4.2'
|
30
|
+
spec.add_dependency "activemodel", '~> 4.2'
|
31
|
+
spec.add_dependency "virtus", "~> 1.0.2"
|
32
|
+
spec.add_dependency "validates_timeliness", "~> 3.0.15"
|
33
|
+
end
|