tablets 0.1.0
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/MIT-LICENSE +20 -0
- data/README.md +90 -0
- data/Rakefile +19 -0
- data/app/assets/javascripts/tablets/callbacks.js.coffee +3 -0
- data/app/assets/javascripts/tablets/tablet.js.coffee +35 -0
- data/app/assets/javascripts/tablets.js.coffee +4 -0
- data/app/controllers/tablets/ajax_controller.rb +31 -0
- data/app/views/tablets/_tablet.html.erb +21 -0
- data/config/routes.rb +3 -0
- data/lib/tablets/data/processing/base.rb +23 -0
- data/lib/tablets/data/processing/filter.rb +47 -0
- data/lib/tablets/data/processing/order.rb +34 -0
- data/lib/tablets/data/processing/paginate.rb +40 -0
- data/lib/tablets/data/query.rb +61 -0
- data/lib/tablets/data.rb +58 -0
- data/lib/tablets/engine.rb +9 -0
- data/lib/tablets/global/configurator.rb +49 -0
- data/lib/tablets/global/loader.rb +37 -0
- data/lib/tablets/global/store.rb +25 -0
- data/lib/tablets/railtie.rb +27 -0
- data/lib/tablets/renderer.rb +84 -0
- data/lib/tablets/tablet.rb +60 -0
- data/lib/tablets/utils/arel.rb +34 -0
- data/lib/tablets/utils/config.rb +75 -0
- data/lib/tablets/version.rb +3 -0
- data/lib/tablets/view_helpers.rb +14 -0
- data/lib/tablets.rb +19 -0
- data/spec/lib/tablets/data/processing/base_spec.rb +19 -0
- data/spec/lib/tablets/data/processing/paginate_spec.rb +73 -0
- data/spec/lib/tablets/global/store_spec.rb +33 -0
- data/spec/lib/tablets/renderer_spec.rb +102 -0
- data/spec/lib/tablets/utils/config_spec.rb +104 -0
- data/spec/lib/tablets/view_helpers_spec.rb +42 -0
- data/spec/spec_helper.rb +92 -0
- metadata +169 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'tablets/engine'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
# Prepares markup. Renders table without any data.
|
5
|
+
class Renderer
|
6
|
+
# Initializes renderer with tablet and params.
|
7
|
+
def initialize(tablet, params = {})
|
8
|
+
@tablet = tablet
|
9
|
+
@params = params
|
10
|
+
end
|
11
|
+
|
12
|
+
# Renders table in view_context.
|
13
|
+
def render(view_context)
|
14
|
+
view_context.render(partial: 'tablets/tablet', locals: locals)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :params, :tablet
|
20
|
+
|
21
|
+
# Prepares locals for tablet partial.
|
22
|
+
def locals
|
23
|
+
{
|
24
|
+
id: id,
|
25
|
+
name: tablet.name,
|
26
|
+
columns: tablet.columns,
|
27
|
+
options: options,
|
28
|
+
params: params
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
# Id for HTML container. Includes name and params with values.
|
33
|
+
#
|
34
|
+
# renderer = Tablets::Renderer.new(:posts, user_id: 1)
|
35
|
+
# renderer.id #=> 'posts_user_id_1'
|
36
|
+
#
|
37
|
+
def id
|
38
|
+
[tablet.name, params.to_a].flatten.map(&:to_s).join('_')
|
39
|
+
end
|
40
|
+
|
41
|
+
# Calculates resulting options.
|
42
|
+
def options
|
43
|
+
@options ||= {}
|
44
|
+
.merge(Tablets.options)
|
45
|
+
.merge(columnDefs: columns_definitions, ajax: data_path)
|
46
|
+
.merge(tablet.options)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Calculates column options and applies options on top.
|
50
|
+
#
|
51
|
+
# ...
|
52
|
+
# columns do
|
53
|
+
# [{
|
54
|
+
# title: 'Title',
|
55
|
+
# order: 'posts.title',
|
56
|
+
# data: :title,
|
57
|
+
# options: { className: 'post-title' }
|
58
|
+
# }]
|
59
|
+
# end
|
60
|
+
# ...
|
61
|
+
#
|
62
|
+
# renderer.columns_definitions #=> [{
|
63
|
+
# targets: 0,
|
64
|
+
# searchable: false,
|
65
|
+
# orderable: true,
|
66
|
+
# className: 'post-title'
|
67
|
+
# }]
|
68
|
+
#
|
69
|
+
def columns_definitions
|
70
|
+
tablet.columns.map.with_index do |column, index|
|
71
|
+
{
|
72
|
+
targets: index,
|
73
|
+
searchable: column[:search].present?,
|
74
|
+
orderable: column[:order].present?
|
75
|
+
}.merge!(column[:options] || {})
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns path to data.
|
80
|
+
def data_path
|
81
|
+
Tablets::Engine.routes.url_helpers.data_path(tablet.name)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'tablets/utils/config'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
# Incapsulates tablet related information.
|
5
|
+
class Tablet
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
# Initializes tablet with name, callbacks fed with block.
|
9
|
+
def initialize(name, &block)
|
10
|
+
@name = name
|
11
|
+
@config = Tablets::Utils::Config.new(&block)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns general jquery-datatable configuration overrides.
|
15
|
+
# By default returns empty options.
|
16
|
+
def options
|
17
|
+
call(:options) { {} }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Determines is user authorized.
|
21
|
+
# By default returns true.
|
22
|
+
def authorize(controller)
|
23
|
+
call(:authorize, controller) { true }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Allows to make additional processing before records would be used.
|
27
|
+
# By default returns records.
|
28
|
+
def process(records)
|
29
|
+
call(:process, records) { records }
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns details HTML for the record.
|
33
|
+
# By default returns nil.
|
34
|
+
def details(record)
|
35
|
+
call(:details, record) { nil }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns columns definitions.
|
39
|
+
# Required.
|
40
|
+
def columns
|
41
|
+
call(:columns)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns database relation to fetch data.
|
45
|
+
# Required.
|
46
|
+
def relation(params)
|
47
|
+
call(:relation, params)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
# Calls callback.
|
53
|
+
# Clarifies error message on error.
|
54
|
+
def call(callback, *params, &block)
|
55
|
+
@config.call(callback, *params, &block)
|
56
|
+
rescue ArgumentError
|
57
|
+
raise ArgumentError, "Please define #{callback} for '#{name}' tablet."
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Tablets
|
2
|
+
module Utils
|
3
|
+
# Arel related utils.
|
4
|
+
module Arel
|
5
|
+
class << self
|
6
|
+
# Casting arel column using db specific type.
|
7
|
+
def column(column)
|
8
|
+
model, column = column.split('.')
|
9
|
+
model = model.singularize.titleize.gsub(/ /, '').constantize
|
10
|
+
|
11
|
+
::Arel::Nodes::NamedFunction.new(
|
12
|
+
'CAST', [model.arel_table[column.to_sym].as(typecast)]
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# Returns database specific string type.
|
19
|
+
def typecast
|
20
|
+
case db_adapter
|
21
|
+
when :postgresql then 'VARCHAR'
|
22
|
+
when :mysql2 then 'CHAR'
|
23
|
+
when :sqlite3 then 'TEXT'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Retrieves rails database adapter.
|
28
|
+
def db_adapter
|
29
|
+
ActiveRecord::Base.configurations[Rails.env]['adapter'].to_sym
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Tablets
|
2
|
+
module Utils
|
3
|
+
# Config utility. Allows to write configs in declarative form.
|
4
|
+
# And fetch values with defaults.
|
5
|
+
#
|
6
|
+
# config = Config.new do
|
7
|
+
# some_var 32
|
8
|
+
# another_var 42
|
9
|
+
#
|
10
|
+
# some_callback do |arg|
|
11
|
+
# do_something_with arg
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# config.get(:some_var) #=> 32
|
16
|
+
# config.get(:non_existent_var) #=> ArgumentError
|
17
|
+
# config.get(:non_existent_var, 'default') #=> 'default'
|
18
|
+
#
|
19
|
+
# config.call(:some_callback, 'my_arg') { |arg| default_action arg }
|
20
|
+
#
|
21
|
+
class Config
|
22
|
+
# Initializes config with block.
|
23
|
+
# Block is optional and can be applied later.
|
24
|
+
def initialize(&block)
|
25
|
+
@hash = {}
|
26
|
+
|
27
|
+
apply(&block) unless block.nil?
|
28
|
+
end
|
29
|
+
|
30
|
+
# Executes block in config context.
|
31
|
+
def apply(&block)
|
32
|
+
instance_eval(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns value.
|
36
|
+
# If no value defined, returns default.
|
37
|
+
# If no default raises ArgumentError.
|
38
|
+
def get(name, default = nil, &default_block)
|
39
|
+
value = @hash[name][0] if @hash[name]
|
40
|
+
|
41
|
+
if !value.nil?
|
42
|
+
value
|
43
|
+
elsif !default.nil?
|
44
|
+
default
|
45
|
+
elsif !default_block.nil?
|
46
|
+
default_block.call
|
47
|
+
else
|
48
|
+
fail ArgumentError, "Value :#{name} is not set."
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Calls callback.
|
53
|
+
# If no calbback defined, calls default.
|
54
|
+
# If no default raises ArgumentError.
|
55
|
+
def call(name, *params, &default)
|
56
|
+
callback = @hash[name][0] if @hash[name]
|
57
|
+
|
58
|
+
if !callback.nil?
|
59
|
+
callback.call(*params)
|
60
|
+
elsif !default.nil?
|
61
|
+
default.call(*params)
|
62
|
+
else
|
63
|
+
fail ArgumentError, "Callback :#{name} is not registered."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
# Gathers all calls.
|
70
|
+
def method_missing(name, *args, &block)
|
71
|
+
@hash[name] = [*args, block]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'tablets/renderer'
|
2
|
+
|
3
|
+
module Tablets
|
4
|
+
# View helpers included to Rails.
|
5
|
+
module ViewHelpers
|
6
|
+
# Finds tablet by name and renders is with params in current view context.
|
7
|
+
#
|
8
|
+
# <%= render_tablet :posts, user_id: @user.id %>
|
9
|
+
#
|
10
|
+
def render_tablet(name, params = {})
|
11
|
+
Tablets::Renderer.new(Tablets[name], params).render(self)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/tablets.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'tablets/global/loader'
|
2
|
+
require 'tablets/global/store'
|
3
|
+
require 'tablets/global/configurator'
|
4
|
+
|
5
|
+
# Top level tablets module. Extended with global tablets methods.
|
6
|
+
module Tablets
|
7
|
+
autoload :Data, 'tablets/data'
|
8
|
+
|
9
|
+
extend Tablets::Global::Loader
|
10
|
+
extend Tablets::Global::Store
|
11
|
+
extend Tablets::Global::Configurator
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'tablets/version'
|
15
|
+
|
16
|
+
require 'tablets/tablet'
|
17
|
+
|
18
|
+
require 'tablets/railtie'
|
19
|
+
require 'tablets/engine'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tablets/data/processing/base'
|
4
|
+
|
5
|
+
RSpec.describe Tablets::Data::Processing::Base do
|
6
|
+
subject { Tablets::Data::Processing::Base.new(params, columns) }
|
7
|
+
|
8
|
+
let(:relation) { 'relation' }
|
9
|
+
let(:params) { 'params' }
|
10
|
+
let(:columns) { 'columns' }
|
11
|
+
|
12
|
+
describe '#apply' do
|
13
|
+
it 'raises not implemented error' do
|
14
|
+
expect do
|
15
|
+
subject.apply(relation)
|
16
|
+
end.to raise_error(NotImplementedError)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tablets/data/processing/paginate'
|
4
|
+
|
5
|
+
RSpec.describe Tablets::Data::Processing::Paginate do
|
6
|
+
subject { Tablets::Data::Processing::Paginate.new(params, columns) }
|
7
|
+
|
8
|
+
let(:relation) { double }
|
9
|
+
let(:params) { { start: start, length: length } }
|
10
|
+
let(:columns) { 'columns' }
|
11
|
+
|
12
|
+
describe '#apply' do
|
13
|
+
before do
|
14
|
+
allow(relation).to receive(:offset).with(anything).and_return(relation)
|
15
|
+
allow(relation).to receive(:limit).with(anything).and_return(relation)
|
16
|
+
end
|
17
|
+
|
18
|
+
let!(:result) { subject.apply(relation) }
|
19
|
+
|
20
|
+
context 'if start matches beginning of page' do
|
21
|
+
let(:start) { 30 }
|
22
|
+
let(:length) { 15 }
|
23
|
+
|
24
|
+
it 'applies start' do
|
25
|
+
expect(relation).to have_received(:offset).with(start)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'applies length' do
|
29
|
+
expect(relation).to have_received(:limit).with(length)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'returns relation' do
|
33
|
+
expect(result).to eq(relation)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'if start not matches beginning of page' do
|
38
|
+
let(:start) { 25 }
|
39
|
+
let(:page_start) { 15 }
|
40
|
+
let(:length) { 15 }
|
41
|
+
|
42
|
+
it 'applies page start' do
|
43
|
+
expect(relation).to have_received(:offset).with(page_start)
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'applies length' do
|
47
|
+
expect(relation).to have_received(:limit).with(length)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'returns relation' do
|
51
|
+
expect(result).to eq(relation)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context 'without length' do
|
56
|
+
let(:default_length) { 10 }
|
57
|
+
let(:start) { 10 }
|
58
|
+
let(:params) { { start: start } }
|
59
|
+
|
60
|
+
it 'applies offset' do
|
61
|
+
expect(relation).to have_received(:offset)
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'applies default length' do
|
65
|
+
expect(relation).to have_received(:limit).with(default_length)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'returns relation' do
|
69
|
+
expect(result).to eq(relation)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tablets/global/store'
|
4
|
+
|
5
|
+
RSpec.describe Tablets::Global::Store do
|
6
|
+
subject { Object.new.tap { |object| object.extend(Tablets::Global::Store) } }
|
7
|
+
|
8
|
+
describe '#register' do
|
9
|
+
let(:name) { :posts }
|
10
|
+
let(:block) { proc {} }
|
11
|
+
let(:tablet) { double }
|
12
|
+
|
13
|
+
before do
|
14
|
+
subject.instance_eval { @tablets = {} }
|
15
|
+
allow(Tablets::Tablet).to receive(:new).with(name, &block)
|
16
|
+
.and_return(tablet)
|
17
|
+
end
|
18
|
+
|
19
|
+
let!(:result) { subject.register(name, &block) }
|
20
|
+
|
21
|
+
it 'initializes tablet' do
|
22
|
+
expect(Tablets::Tablet).to have_received(:new).with(name, &block)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'stores tablet' do
|
26
|
+
expect(subject.tablets).to eq(name => tablet)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'delegates [] to tablets' do
|
30
|
+
expect(subject[name]).to eq(subject.tablets[name])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tablets'
|
4
|
+
require 'tablets/renderer'
|
5
|
+
|
6
|
+
RSpec.describe Tablets::Renderer do
|
7
|
+
subject { Tablets::Renderer.new(tablet, params) }
|
8
|
+
|
9
|
+
describe '#render' do
|
10
|
+
let(:tablet) { double }
|
11
|
+
let(:params) { { user_id: 1 } }
|
12
|
+
|
13
|
+
let(:render_result) { 'result' }
|
14
|
+
let(:path) { 'path' }
|
15
|
+
|
16
|
+
let(:tablet_name) { :posts }
|
17
|
+
let(:tablet_columns) do
|
18
|
+
[{
|
19
|
+
title: 'Title',
|
20
|
+
order: 'posts.title',
|
21
|
+
data: :title,
|
22
|
+
options: { className: 'post-title' }
|
23
|
+
}, {
|
24
|
+
title: 'User',
|
25
|
+
order: ['users.first_name', 'users.last_name'],
|
26
|
+
data: :user,
|
27
|
+
search: ['users.first_name', 'users.last_name']
|
28
|
+
}]
|
29
|
+
end
|
30
|
+
let(:tablet_options) { { some_option: :some_value } }
|
31
|
+
|
32
|
+
let(:options) do
|
33
|
+
{
|
34
|
+
ajax: path,
|
35
|
+
columnDefs: [{
|
36
|
+
targets: 0,
|
37
|
+
searchable: false,
|
38
|
+
orderable: true,
|
39
|
+
className: 'post-title'
|
40
|
+
}, {
|
41
|
+
targets: 1,
|
42
|
+
searchable: true,
|
43
|
+
orderable: true
|
44
|
+
}]
|
45
|
+
}.merge!(tablet_options)
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:view_context) { double }
|
49
|
+
|
50
|
+
before do
|
51
|
+
allow(tablet).to receive_messages(
|
52
|
+
name: tablet_name, columns: tablet_columns, options: tablet_options
|
53
|
+
)
|
54
|
+
|
55
|
+
allow(Tablets::Engine).to receive_message_chain(
|
56
|
+
:routes, :url_helpers, :data_path
|
57
|
+
).and_return(path)
|
58
|
+
|
59
|
+
allow(view_context).to receive(:render).and_return(render_result)
|
60
|
+
end
|
61
|
+
|
62
|
+
let!(:result) { subject.render(view_context) }
|
63
|
+
|
64
|
+
def locals(local)
|
65
|
+
hash_including(locals: hash_including(local))
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'renders tablets partial' do
|
69
|
+
expect(view_context).to have_received(:render).with(
|
70
|
+
hash_including(partial: 'tablets/tablet')
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'passes correct id as partial locals' do
|
75
|
+
expect(view_context).to have_received(:render).with(
|
76
|
+
locals(id: 'posts_user_id_1')
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'passes correct columns as partial locals' do
|
81
|
+
expect(view_context).to have_received(:render).with(
|
82
|
+
locals(columns: tablet_columns)
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'passes correct config as partial locals' do
|
87
|
+
expect(view_context).to have_received(:render).with(
|
88
|
+
locals(options: hash_including(options))
|
89
|
+
)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'passes correct params as partial locals' do
|
93
|
+
expect(view_context).to have_received(:render).with(
|
94
|
+
locals(params: params)
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'returns render result' do
|
99
|
+
expect(result).to eq(render_result)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tablets/utils/config'
|
4
|
+
|
5
|
+
RSpec.describe Tablets::Utils::Config do
|
6
|
+
subject { Tablets::Utils::Config.new(&block) }
|
7
|
+
|
8
|
+
def hash
|
9
|
+
subject.instance_eval { @hash }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#initialize' do
|
13
|
+
context 'with block' do
|
14
|
+
let(:block) { proc { var('val') } }
|
15
|
+
|
16
|
+
it 'applies block to config' do
|
17
|
+
expect(hash).to_not be_empty
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'without block' do
|
22
|
+
let(:block) { nil }
|
23
|
+
|
24
|
+
it 'initializes empty config' do
|
25
|
+
expect(hash).to be_empty
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#apply' do
|
31
|
+
let(:block) { nil }
|
32
|
+
let(:another_block) { proc { var('val') } }
|
33
|
+
|
34
|
+
it 'applies block' do
|
35
|
+
subject.apply(&another_block)
|
36
|
+
|
37
|
+
expect(hash).to_not be_empty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#get' do
|
42
|
+
context 'if value exists' do
|
43
|
+
let(:block) { proc { var('val') } }
|
44
|
+
|
45
|
+
it 'returns value' do
|
46
|
+
expect(subject.get(:var)).to eq('val')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'if value not exists' do
|
51
|
+
let(:block) {}
|
52
|
+
|
53
|
+
it 'raises error' do
|
54
|
+
expect do
|
55
|
+
subject.get(:var)
|
56
|
+
end.to raise_error(ArgumentError)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'if value not exists but have default' do
|
61
|
+
let(:block) {}
|
62
|
+
|
63
|
+
it 'returns default' do
|
64
|
+
expect(subject.get(:var, 'default')).to eq('default')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'if value not exists but have default block' do
|
69
|
+
let(:block) {}
|
70
|
+
|
71
|
+
it 'returns default block return value' do
|
72
|
+
expect(subject.get(:var) { 'default' }).to eq('default')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe '#call' do
|
78
|
+
context 'if callback exists' do
|
79
|
+
let(:block) { proc { var { 'val' } } }
|
80
|
+
|
81
|
+
it 'returns callback return value' do
|
82
|
+
expect(subject.call(:var)).to eq('val')
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'if callback not exists' do
|
87
|
+
let(:block) {}
|
88
|
+
|
89
|
+
it 'raises error' do
|
90
|
+
expect do
|
91
|
+
subject.call(:var)
|
92
|
+
end.to raise_error(ArgumentError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'if value not exists but have default block' do
|
97
|
+
let(:block) {}
|
98
|
+
|
99
|
+
it 'returns default block return value' do
|
100
|
+
expect(subject.call(:var) { 'default' }).to eq('default')
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'tablets'
|
4
|
+
require 'tablets/view_helpers'
|
5
|
+
|
6
|
+
RSpec.describe Tablets::ViewHelpers do
|
7
|
+
subject { Object.new.tap { |object| object.extend(Tablets::ViewHelpers) } }
|
8
|
+
|
9
|
+
describe '#render_tablet' do
|
10
|
+
let(:name) { :name }
|
11
|
+
let(:params) { 'params' }
|
12
|
+
let(:tablet) { double }
|
13
|
+
let(:renderer) { double }
|
14
|
+
let(:render_result) { 'render_result' }
|
15
|
+
|
16
|
+
before do
|
17
|
+
allow(Tablets).to receive(:[]).with(name).and_return(tablet)
|
18
|
+
allow(Tablets::Renderer).to receive(:new).with(tablet, params)
|
19
|
+
.and_return(renderer)
|
20
|
+
allow(renderer).to receive(:render).with(subject)
|
21
|
+
.and_return(render_result)
|
22
|
+
end
|
23
|
+
|
24
|
+
let!(:result) { subject.render_tablet(name, params) }
|
25
|
+
|
26
|
+
it 'finds tablet' do
|
27
|
+
expect(Tablets).to have_received(:[]).with(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'initializes renderer' do
|
31
|
+
expect(Tablets::Renderer).to have_received(:new).with(tablet, params)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'renders in current view context' do
|
35
|
+
expect(renderer).to have_received(:render).with(subject)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns render result' do
|
39
|
+
expect(result).to eq(render_result)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|