tablets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|