frigate 0.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 +19 -0
- data/.rspec +2 -0
- data/.travis.yml +7 -0
- data/Gemfile +10 -0
- data/Guardfile +67 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +13 -0
- data/frigate.gemspec +31 -0
- data/lib/frigate/form/association.rb +94 -0
- data/lib/frigate/form/base.rb +141 -0
- data/lib/frigate/form/property.rb +40 -0
- data/lib/frigate/form/synchronizer/base.rb +22 -0
- data/lib/frigate/form/synchronizer/basic.rb +75 -0
- data/lib/frigate/form/synchronizer/contract.rb +46 -0
- data/lib/frigate/form/synchronizer/form.rb +40 -0
- data/lib/frigate/form/synchronizer/fundamental.rb +17 -0
- data/lib/frigate/form/synchronizer.rb +14 -0
- data/lib/frigate/form.rb +16 -0
- data/lib/frigate/function.rb +41 -0
- data/lib/frigate/operation/action/base.rb +65 -0
- data/lib/frigate/operation/action/create.rb +21 -0
- data/lib/frigate/operation/action/update.rb +24 -0
- data/lib/frigate/operation/action.rb +12 -0
- data/lib/frigate/operation/base.rb +79 -0
- data/lib/frigate/operation/controller.rb +42 -0
- data/lib/frigate/operation/invalid_params_error.rb +7 -0
- data/lib/frigate/operation/renderable.rb +52 -0
- data/lib/frigate/operation/worker.rb +50 -0
- data/lib/frigate/operation.rb +16 -0
- data/lib/frigate/version.rb +3 -0
- data/lib/frigate.rb +61 -0
- data/spec/fixtures/user_form.rb +34 -0
- data/spec/frigate/form/base_spec.rb +120 -0
- data/spec/frigate/operation/base_spec.rb +52 -0
- data/spec/rails_test_app/Rakefile +6 -0
- data/spec/rails_test_app/app/controllers/application_controller.rb +5 -0
- data/spec/rails_test_app/app/helpers/application_helper.rb +2 -0
- data/spec/rails_test_app/app/models/user/profile/passport.rb +5 -0
- data/spec/rails_test_app/app/models/user/profile.rb +6 -0
- data/spec/rails_test_app/app/models/user.rb +5 -0
- data/spec/rails_test_app/bin/bundle +3 -0
- data/spec/rails_test_app/bin/rails +4 -0
- data/spec/rails_test_app/bin/rake +4 -0
- data/spec/rails_test_app/config/application.rb +30 -0
- data/spec/rails_test_app/config/boot.rb +4 -0
- data/spec/rails_test_app/config/database.yml +25 -0
- data/spec/rails_test_app/config/environment.rb +5 -0
- data/spec/rails_test_app/config/environments/development.rb +28 -0
- data/spec/rails_test_app/config/environments/production.rb +67 -0
- data/spec/rails_test_app/config/environments/test.rb +39 -0
- data/spec/rails_test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails_test_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/rails_test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/rails_test_app/config/initializers/inflections.rb +16 -0
- data/spec/rails_test_app/config/initializers/mime_types.rb +4 -0
- data/spec/rails_test_app/config/initializers/session_store.rb +3 -0
- data/spec/rails_test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails_test_app/config/locales/en.yml +23 -0
- data/spec/rails_test_app/config/routes.rb +56 -0
- data/spec/rails_test_app/config/secrets.yml +22 -0
- data/spec/rails_test_app/config.ru +4 -0
- data/spec/rails_test_app/db/migrate/20141212054646_create_users.rb +10 -0
- data/spec/rails_test_app/db/migrate/20141212054746_create_user_profiles.rb +10 -0
- data/spec/rails_test_app/db/migrate/20141212054847_create_user_profile_passports.rb +15 -0
- data/spec/rails_test_app/db/seeds.rb +7 -0
- data/spec/spec_helper.rb +84 -0
- metadata +217 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Form
|
|
3
|
+
# Serves for synchronization form properties with model attributes/properties
|
|
4
|
+
module Synchronizer
|
|
5
|
+
# An abstract syncronizator, needs to be as superclass
|
|
6
|
+
class Fundamental
|
|
7
|
+
attr_reader :form
|
|
8
|
+
|
|
9
|
+
# initializes class, rly?????
|
|
10
|
+
# @param [Frigate::Form] form
|
|
11
|
+
def initialize(form)
|
|
12
|
+
@form = form
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Form
|
|
3
|
+
# Serves for synchronization form properties with model attributes/properties
|
|
4
|
+
module Synchronizer
|
|
5
|
+
# code; mb some configs
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
#
|
|
10
|
+
require 'frigate/form/synchronizer/fundamental'
|
|
11
|
+
require 'frigate/form/synchronizer/base'
|
|
12
|
+
require 'frigate/form/synchronizer/basic'
|
|
13
|
+
require 'frigate/form/synchronizer/form'
|
|
14
|
+
require 'frigate/form/synchronizer/contract'
|
data/lib/frigate/form.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Is used for model validation outside of model
|
|
3
|
+
#
|
|
4
|
+
# @author Vladislav Pauk <vladislavpauk@gmail.com>
|
|
5
|
+
#
|
|
6
|
+
require 'active_support/core_ext/module/delegation'
|
|
7
|
+
#
|
|
8
|
+
module Frigate
|
|
9
|
+
# It's a form.
|
|
10
|
+
# @see Frigate::Form::Base
|
|
11
|
+
module Form
|
|
12
|
+
# code, mb some configuration
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
#
|
|
16
|
+
require 'frigate/form/base'
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# @example
|
|
2
|
+
# class Song::AddArtistService < Frigate::Service
|
|
3
|
+
# property :song
|
|
4
|
+
# property :artist
|
|
5
|
+
#
|
|
6
|
+
# def function
|
|
7
|
+
# song.artists << artist
|
|
8
|
+
# end
|
|
9
|
+
# end
|
|
10
|
+
#
|
|
11
|
+
# Song::AddArtistService[song: song, artist: artist]
|
|
12
|
+
class Frigate::Function
|
|
13
|
+
class << self
|
|
14
|
+
# @param [Symbol] name
|
|
15
|
+
def property(name)
|
|
16
|
+
class_eval { attr_reader name }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# @param [Hash] attrs
|
|
20
|
+
def run(attrs)
|
|
21
|
+
new(attrs).run
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
alias_method :[], :run
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @param [Hash] attrs
|
|
28
|
+
def initialize(attrs)
|
|
29
|
+
attrs.each { |key, val| instance_variable_set("@#{key}", val) }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# to perform/run the service actions\tasks
|
|
33
|
+
def run
|
|
34
|
+
function
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# here you should write your function code =)
|
|
38
|
+
def function
|
|
39
|
+
raise NotImplemented
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
module Action
|
|
4
|
+
# Base class is an abstact class
|
|
5
|
+
# @abstract
|
|
6
|
+
class Base
|
|
7
|
+
class << self
|
|
8
|
+
# Initializes action class and pass args to instance run method
|
|
9
|
+
# @param [Frigate::Operation] operation receives an instace of subclass of Frigate::Operation
|
|
10
|
+
# @param [Hash] params
|
|
11
|
+
# @param [Hash] opts
|
|
12
|
+
def run(operation, params, opts={})
|
|
13
|
+
new(operation, opts).run(params)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_reader :opts, :operation, :model, :model_form, :action_result, :params
|
|
18
|
+
|
|
19
|
+
# @param [Frigate::Operation] operation
|
|
20
|
+
# @param [Hash] opts
|
|
21
|
+
def initialize(operation, opts={})
|
|
22
|
+
@operation = operation
|
|
23
|
+
@opts = opts
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Runs action's mechanism
|
|
27
|
+
def run(params)
|
|
28
|
+
(@params = params); action; model_form
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# You should define an action in here
|
|
32
|
+
def action
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
protected
|
|
37
|
+
|
|
38
|
+
# Gets a model class of defined model class for operation
|
|
39
|
+
def model_klass
|
|
40
|
+
operation.class.model_klass
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Creates an instance of operation subclass of Frigate::Form for given model
|
|
44
|
+
def create_form(model)
|
|
45
|
+
operation.class.form_class.new(model)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# A getter/caller of operation_block from an operation class variable *operation_block*
|
|
49
|
+
# @note if no args passed then return the value of class variable *operation_block*
|
|
50
|
+
# @note if args passed then class variable *operation_block* is going to be called with these args
|
|
51
|
+
def operation_block(*args)
|
|
52
|
+
if args.empty?
|
|
53
|
+
operation.class.operation_block
|
|
54
|
+
else
|
|
55
|
+
if operation_block.nil?
|
|
56
|
+
raise StandardError.new('operation_block is nil')
|
|
57
|
+
else
|
|
58
|
+
operation.class.operation_block.call(*args)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
module Action
|
|
4
|
+
# Is here to perform create action of operation
|
|
5
|
+
class Create < Base
|
|
6
|
+
# An create action is defined in here
|
|
7
|
+
def action
|
|
8
|
+
@model = model_klass.new
|
|
9
|
+
@model_form = create_form(model)
|
|
10
|
+
if model_form.validate(params)
|
|
11
|
+
if operation_block
|
|
12
|
+
operation_block(model, params)
|
|
13
|
+
else
|
|
14
|
+
model_form.sync_with_model(save: true)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
module Action
|
|
4
|
+
# Is here to perform update action of operation
|
|
5
|
+
class Update < Base
|
|
6
|
+
# An update action is defined in here
|
|
7
|
+
def action
|
|
8
|
+
@model = model_klass.find_by_id(params[:id]) # TODO: add id verification
|
|
9
|
+
@model_form = create_form(model)
|
|
10
|
+
if model_form.validate(params)
|
|
11
|
+
if operation_block
|
|
12
|
+
operation_block(model, params)
|
|
13
|
+
else
|
|
14
|
+
model_form.sync_with_model(save: true)
|
|
15
|
+
end
|
|
16
|
+
else
|
|
17
|
+
exception = InvalidParamsError.new('invalid params in %s' % operation.class.name)
|
|
18
|
+
raise (exception.tap { |e| e.errors = model_form.errors })
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
# This module consists action classes for operation
|
|
4
|
+
module Action
|
|
5
|
+
# code; mb some configs
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
#
|
|
10
|
+
require 'frigate/operation/action/base'
|
|
11
|
+
require 'frigate/operation/action/create'
|
|
12
|
+
require 'frigate/operation/action/update'
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
# Is here initialize the whole operation class
|
|
4
|
+
# A bigger description will be available soon
|
|
5
|
+
class Base
|
|
6
|
+
ALLOWED_ACTIONS = [:create, :update]
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
# Initializes form class and serves as a getter method
|
|
10
|
+
def form_class
|
|
11
|
+
@form_class ||= Class.new(Frigate::Form::Base)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Serves as a getter method for *model_klass* class variable
|
|
15
|
+
def model_klass
|
|
16
|
+
@model_klass ? @model_klass : (raise StandardError.new('@model_klass nil'))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Serves as a getter method for *operation_action* class variable
|
|
20
|
+
def operation_action
|
|
21
|
+
@operation_action ? @operation_action : (raise StandardError.new('@operation_action nil'))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Serves as a getter method for *operation_block* class variable
|
|
25
|
+
def operation_block
|
|
26
|
+
# @operation_block.is_a?(Proc) ? @operation_block : (raise StandardError.new('operation block is not a Proc'))
|
|
27
|
+
@operation_block
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# @param [Class] model_klass
|
|
31
|
+
def model(model_klass)
|
|
32
|
+
@model_klass = model_klass
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @param [Symbol] action
|
|
36
|
+
def action(action)
|
|
37
|
+
ALLOWED_ACTIONS.include?(action) ? (@operation_action = action.to_sym) : (raise ArgumentError.new('action is invalid'))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# @param [Proc] block
|
|
41
|
+
def operation(&block)
|
|
42
|
+
@operation_block = block
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
delegate :property, :has_one, to: :form_class
|
|
46
|
+
|
|
47
|
+
# @param [Hash] params
|
|
48
|
+
# @param [Hash] opts
|
|
49
|
+
def run(params, opts={})
|
|
50
|
+
new(opts).run(params)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
attr_reader :params, :opts, :model_form
|
|
55
|
+
|
|
56
|
+
delegate :errors, :model, to: :model_form
|
|
57
|
+
|
|
58
|
+
# @param [Hash] opts
|
|
59
|
+
def initialize(opts={})
|
|
60
|
+
@opts = opts
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Runs the whole operation mechanism
|
|
64
|
+
# @param [Hash] params
|
|
65
|
+
# @return [Frigate::Operations] returns self
|
|
66
|
+
def run(params)
|
|
67
|
+
@params = Hashie::Mash.new(params)
|
|
68
|
+
# running actions
|
|
69
|
+
case self.class.operation_action
|
|
70
|
+
when :update
|
|
71
|
+
@model_form = Action::Update.run(self, params)
|
|
72
|
+
else
|
|
73
|
+
@model_form = Action::Create.run(self, params)
|
|
74
|
+
end
|
|
75
|
+
self # return self
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
require 'active_support/concern'
|
|
2
|
+
module Frigate
|
|
3
|
+
module Operation
|
|
4
|
+
# Some stuff for controllers
|
|
5
|
+
module Controller
|
|
6
|
+
# Helpers for rails controllers
|
|
7
|
+
module Helpers
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
included do
|
|
11
|
+
rescue_from InvalidParamsError, with: :invalid_params_error
|
|
12
|
+
|
|
13
|
+
def invalid_params_error(exception)
|
|
14
|
+
respond_to do |f|
|
|
15
|
+
f.json do
|
|
16
|
+
render status: 400, json: {
|
|
17
|
+
status: 'error',
|
|
18
|
+
data: exception.errors.messages
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# run-operation helps to run operation elegantly
|
|
26
|
+
# @param [Frigate::Operation] klass
|
|
27
|
+
# @param [Hash] params
|
|
28
|
+
def run_operation(klass, params)
|
|
29
|
+
klass.run(params)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# render-operation helps to render operation data
|
|
33
|
+
# @param [Frigate::Operation] klass
|
|
34
|
+
# @param [Hash] params
|
|
35
|
+
def render_operation(*args)
|
|
36
|
+
run_operation(*args).render(self)
|
|
37
|
+
# raise run_operation(*args).errors.messages.inspect
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
# allows operation to be rendered as json for now))
|
|
4
|
+
module Renderable
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
def render_block
|
|
11
|
+
@render_block
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def render(render_block)
|
|
15
|
+
if render_block.is_a?(Proc)
|
|
16
|
+
@render_block ||= render_block
|
|
17
|
+
else
|
|
18
|
+
raise StandardError.new('render_block is not a Proc')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @param [ActionController::Base] ctrl An Instance of subclass of ActionController::Base
|
|
24
|
+
def render(ctrl)
|
|
25
|
+
ctrl.respond_to do |f|
|
|
26
|
+
f.json do
|
|
27
|
+
ctrl.render status: (model_form.valid? ? 200 : 400), json: build_json(ctrl)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
private
|
|
33
|
+
|
|
34
|
+
# @param [ActionController::Base] ctrl An Instance of subclass of ActionController::Base
|
|
35
|
+
def build_json(ctrl)
|
|
36
|
+
if model_form.valid?
|
|
37
|
+
Jbuilder.new { |_j| _j.status 'success'; _j.data { render_op(_j, self, ctrl) } }.target!
|
|
38
|
+
else
|
|
39
|
+
Jbuilder.new do |_j|
|
|
40
|
+
_j.status 'error'
|
|
41
|
+
_j.errors errors.messages
|
|
42
|
+
end.target!
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def render_op(*args)
|
|
48
|
+
self.class.render_block.call(*args) if self.class.render_block.is_a?(Proc)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
module Frigate
|
|
2
|
+
module Operation
|
|
3
|
+
# A module that allows operation to perform as a background job, using Sidekiq as BJ for now
|
|
4
|
+
module Worker
|
|
5
|
+
# Included hook
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.send(:include, Sidekiq::Worker) # TODO: this will work with any background gem.
|
|
8
|
+
base.extend(ClassMethods)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Class methods of class that includes *Worker* module
|
|
12
|
+
module ClassMethods
|
|
13
|
+
# Overrides standard *run* method in order to run an operation as a background job
|
|
14
|
+
# @param [Hash] params
|
|
15
|
+
# @param [Hash] options
|
|
16
|
+
def run(params, options = {})
|
|
17
|
+
serialized_params = serialize_params(params)
|
|
18
|
+
is_background? ? perform_async(serialized_params) : new.perform(serialized_params)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Whether or not operation is background
|
|
22
|
+
# @return [Boolean] either background or not
|
|
23
|
+
def is_background?
|
|
24
|
+
!(Rails.env.test? || Rails.env.cucumber?) ||
|
|
25
|
+
(!ENV['FRIGATE_WORKER'].nil? || ENV['FRIGATE_WORKER'].downcase == 'true')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
private
|
|
29
|
+
# serializes params
|
|
30
|
+
# @param [Hash] params
|
|
31
|
+
def serialize_params(params)
|
|
32
|
+
params # TODO: serialize AR for e.g.
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Method that runs operation mechanism. It's here because of Sidekiq::Worker needs it
|
|
37
|
+
# @param [Hash] params income parameters
|
|
38
|
+
def perform(params)
|
|
39
|
+
run(deserialize_params(params))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
# deserializes params
|
|
44
|
+
# @param [Hash] params
|
|
45
|
+
def deserialize_params(params)
|
|
46
|
+
Hashie::Mash.new(params) # TODO: deserialize AR for e.g.
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'hashie/mash'
|
|
2
|
+
#
|
|
3
|
+
# This class serves as an abstact layer between model and controller
|
|
4
|
+
#
|
|
5
|
+
module Frigate
|
|
6
|
+
module Operation
|
|
7
|
+
# code; mb some configs
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
#
|
|
11
|
+
require 'frigate/operation/invalid_params_error'
|
|
12
|
+
require 'frigate/operation/worker'
|
|
13
|
+
require 'frigate/operation/controller'
|
|
14
|
+
require 'frigate/operation/renderable'
|
|
15
|
+
require 'frigate/operation/action'
|
|
16
|
+
require 'frigate/operation/base'
|
data/lib/frigate.rb
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require "frigate/version"
|
|
2
|
+
require 'active_support/core_ext/object/duplicable'
|
|
3
|
+
require 'active_support/core_ext/object/deep_dup'
|
|
4
|
+
require 'active_support/concern'
|
|
5
|
+
require 'active_model'
|
|
6
|
+
require 'hashie/mash'
|
|
7
|
+
#
|
|
8
|
+
# Description of this module is going to be relised soon
|
|
9
|
+
#
|
|
10
|
+
module Frigate
|
|
11
|
+
end
|
|
12
|
+
#
|
|
13
|
+
# Requiring Frigate's modules
|
|
14
|
+
#
|
|
15
|
+
require 'frigate/form'
|
|
16
|
+
require 'frigate/operation'
|
|
17
|
+
require 'frigate/function'
|
|
18
|
+
#
|
|
19
|
+
# Typecaster for boolean values. Source: http://drawingablank.me/blog/ruby-boolean-typecasting.html
|
|
20
|
+
#
|
|
21
|
+
class String
|
|
22
|
+
def to_bool
|
|
23
|
+
return true if self == true || self =~ (/^(true|t|yes|y|1)$/i)
|
|
24
|
+
return false if self == false || self.blank? || self =~ (/^(false|f|no|n|0)$/i)
|
|
25
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
#
|
|
29
|
+
class Fixnum
|
|
30
|
+
def to_bool
|
|
31
|
+
return true if self == 1
|
|
32
|
+
return false if self == 0
|
|
33
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
#
|
|
37
|
+
class TrueClass
|
|
38
|
+
def to_i;
|
|
39
|
+
1;
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def to_bool;
|
|
43
|
+
self;
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
#
|
|
47
|
+
class FalseClass
|
|
48
|
+
def to_i;
|
|
49
|
+
0;
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def to_bool;
|
|
53
|
+
self;
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
#
|
|
57
|
+
class NilClass
|
|
58
|
+
def to_bool;
|
|
59
|
+
false;
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
class UserForm < Frigate::Form::Base
|
|
2
|
+
property :email, validates: { presence: true }
|
|
3
|
+
has_one :user_profile do
|
|
4
|
+
property :first_name, validates: { presence: true }
|
|
5
|
+
property :last_name
|
|
6
|
+
property :skype
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class UserFormCustom < Frigate::Form::Base
|
|
11
|
+
property :email, validates: { presence: true },
|
|
12
|
+
validate: [
|
|
13
|
+
Proc.new { error(:invalid) unless value =~ /\A([\w+\-].?)+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i },
|
|
14
|
+
]
|
|
15
|
+
has_one :user_profile do
|
|
16
|
+
property :first_name, validates: { presence: true }
|
|
17
|
+
property :last_name
|
|
18
|
+
property :skype
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class UserFormTree < Frigate::Form::Base
|
|
23
|
+
property :email
|
|
24
|
+
has_one :user_profile do
|
|
25
|
+
property :first_name
|
|
26
|
+
property :last_name
|
|
27
|
+
property :skype
|
|
28
|
+
has_one :user_profile_passport do
|
|
29
|
+
property :number
|
|
30
|
+
property :country
|
|
31
|
+
property :city
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Frigate::Form::Base do
|
|
4
|
+
let(:params) { { email: 'z1@zzz.zz', user_profile: { first_name: 'John', last_name: 'Doe', skype: 'johndoe' } } }
|
|
5
|
+
let(:tree_params) { params.tap { |_p| _p[:user_profile][:user_profile_passport] = { number: 'KL1234', country: 'Ukraine', city: 'Kiev' } } }
|
|
6
|
+
let(:user_model) { User.new.tap { |user| user.build_user_profile } }
|
|
7
|
+
let(:user_model_tree) { User.new.tap { |user| user.build_user_profile; user.profile.build_user_profile_passport } }
|
|
8
|
+
|
|
9
|
+
before(:example) do
|
|
10
|
+
@user_model = user_model
|
|
11
|
+
@user_model_tree = user_model_tree
|
|
12
|
+
@user_form = UserForm.new(@user_model)
|
|
13
|
+
@user_form_custom = UserFormCustom.new(@user_model)
|
|
14
|
+
@user_form_tree = UserFormTree.new(@user_model_tree)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context '#valid?' do
|
|
18
|
+
it 'returns true' do
|
|
19
|
+
@user_form.validate(params)
|
|
20
|
+
expect(@user_form.valid?).to be_truthy
|
|
21
|
+
end
|
|
22
|
+
it 'returns false' do
|
|
23
|
+
@user_form.validate({})
|
|
24
|
+
expect(@user_form.valid?).to be_falsey
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context '#errors' do
|
|
29
|
+
it 'messages should not be empty' do
|
|
30
|
+
@user_form.validate({})
|
|
31
|
+
expect(@user_form.errors.messages).not_to be_empty
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
context '#sync_with_model' do
|
|
36
|
+
it 'should sync params with model' do
|
|
37
|
+
@user_form.validate(params)
|
|
38
|
+
@user_form.sync_with_model
|
|
39
|
+
expect(@user_model.email).to eq(params[:email])
|
|
40
|
+
expect(@user_model.user_profile.first_name).to eq(params[:user_profile][:first_name])
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context 'contract' do
|
|
45
|
+
before(:example) do
|
|
46
|
+
@user_form = UserForm.new(@user_model, contract: true)
|
|
47
|
+
@user_form.validate
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context '#valid?' do
|
|
51
|
+
it 'returns false' do
|
|
52
|
+
expect(@user_form.valid?).to be_falsey
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context '#errors' do
|
|
57
|
+
it 'messages should not be empty' do
|
|
58
|
+
expect(@user_form.errors.messages).not_to be_empty
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context 'custom validations' do
|
|
64
|
+
context '#valid?' do
|
|
65
|
+
it 'return true' do
|
|
66
|
+
@user_form_custom.validate(params)
|
|
67
|
+
expect(@user_form_custom.valid?).to be_truthy
|
|
68
|
+
end
|
|
69
|
+
it 'return false' do
|
|
70
|
+
params[:email] = 'bad-email.com'
|
|
71
|
+
@user_form_custom.validate(params)
|
|
72
|
+
expect(@user_form_custom.valid?).to be_falsey
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
context 'long tree' do
|
|
78
|
+
context '#sync_with_model' do
|
|
79
|
+
it 'should sync params with model' do
|
|
80
|
+
@user_form_tree.validate(tree_params)
|
|
81
|
+
@user_form_tree.sync_with_model
|
|
82
|
+
expect(@user_model_tree.profile.passport.number).to eq(params[:user_profile][:user_profile_passport][:number])
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context 'delegation' do
|
|
88
|
+
before(:example) do
|
|
89
|
+
@user_form.validate(params)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'properties' do
|
|
93
|
+
expect(@user_form.email).to be_a(::Frigate::Form::Property)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it 'associations' do
|
|
97
|
+
expect(@user_form.user_profile).to be_a(::Frigate::Form::Association)
|
|
98
|
+
expect(@user_form.user_profile.first_name).to be_a(::Frigate::Form::Property)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
describe Frigate::Form::Property do
|
|
103
|
+
context '#root' do
|
|
104
|
+
it 'should be instance of Frigate::Form::Base' do
|
|
105
|
+
@user_form.validate(params)
|
|
106
|
+
expect(@user_form.email.root).to be_a(Frigate::Form::Base)
|
|
107
|
+
expect(@user_form.user_profile.first_name.root).to be_a(Frigate::Form::Base)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe Frigate::Form::Association do
|
|
113
|
+
context '#root' do
|
|
114
|
+
it 'should be instance of Frigate::Form::Base' do
|
|
115
|
+
@user_form.validate(params)
|
|
116
|
+
expect(@user_form.user_profile.root).to be_a(Frigate::Form::Base)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|