tablets 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f5e96cdb1c2b3d97a936ff7d2c8f9db941468990
4
- data.tar.gz: 5337d9aa657c9c69aa82281778f0fe2316837a4c
3
+ metadata.gz: a1b6c2a3367aa2d3d1a85c849259390a61bd66e9
4
+ data.tar.gz: '093dd43af37ae99f4f5997da3f166af019adf33a'
5
5
  SHA512:
6
- metadata.gz: 90d6403fb216b57abf8e4284f82295ee946b3abce57d5b456f0cfbc2fa343d52ded1c741e71f37d10c3f4e5e0efda68c290dac6e3351469c93328189b2125726
7
- data.tar.gz: c991fccc8065312bf592cdd23f587da5007852c7981187b539e28cab8f6987fd91362c1c53afb0d9ff7f8baec4af0ed1b4c8df649ed320c8a94f65021c012a01
6
+ metadata.gz: 89467c8e0d974dc4763b45752b46ba498af5b48a7bb3db41d4b6120072f5a961482014ede0bca39a7004ef1cb11fb8049c646926cd6816be592341a0802201c0
7
+ data.tar.gz: 57640ae54b8fea65a99457eb403a4243ddec1f9f832d3e7a1b333aad4283a16cc3ee62a3f181efe2361963403628cafd28b144e0ad4870f0deba49c9322eba5e
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/tablets.svg)](http://badge.fury.io/rb/tablets)
4
4
  [![Code Climate](https://codeclimate.com/github/zenedge/tablets/badges/gpa.svg)](https://codeclimate.com/github/zenedge/tablets)
5
+ [![Build Status](https://travis-ci.org/zenedge/tablets.svg?branch=master)](https://travis-ci.org/zenedge/tablets)
5
6
 
6
7
  ## Installation
7
8
 
@@ -36,19 +37,19 @@ mount Tablets::Engine, at: '/tablets'
36
37
  In `app/tablets/posts.rb`:
37
38
 
38
39
  ``` ruby
39
- Tablets.register :posts do
40
+ PostsTablet < Tablets::Base
40
41
  # Authorization logic.
41
- authorize do |controller|
42
+ def authorize(controller)
42
43
  controller.current_user.id == params[:author_id]
43
44
  end
44
45
 
45
46
  # jQuery-datatables options overrides.
46
- options do
47
+ def options
47
48
  { order: [0, 'asc'] }
48
49
  end
49
50
 
50
51
  # Columns definitions.
51
- columns do
52
+ def columns
52
53
  [{
53
54
  title: 'Title',
54
55
  data: :title,
@@ -70,23 +71,23 @@ Tablets.register :posts do
70
71
  end
71
72
 
72
73
  # HTML for details area.
73
- details do |post|
74
+ def details(post)
74
75
  post.content.html_safe
75
76
  end
76
77
 
77
78
  # Process records before extracting data.
78
- process do |posts|
79
+ def process(posts)
79
80
  posts.map { |post| post.use_wrapper }
80
81
  end
81
82
 
82
83
  # Data relation.
83
- relation do |params|
84
+ def relation(params:, **)
84
85
  # Note: users joined to enable ordering.
85
86
  Post.joins(:users).where(user_id: params[:user_id])
86
87
  end
87
88
 
88
89
  # Additional data added to response.
89
- payload do
90
+ def payload
90
91
  { hash_with: 'data' }
91
92
  end
92
93
  end
@@ -10,7 +10,7 @@ module Tablets
10
10
  private
11
11
 
12
12
  def tablet
13
- @tablet ||= Tablets[params[:name].to_sym]
13
+ @tablet ||= Tablets[params[:name].to_s].new
14
14
  end
15
15
 
16
16
  def authorize!
@@ -0,0 +1,65 @@
1
+ module Tablets
2
+ # Incapsulates tablet related information
3
+ class Base
4
+ def self.inherited(child_class)
5
+ tablet_name = child_class.tablet_name
6
+ Tablets.register_tablet(tablet_name, child_class)
7
+ end
8
+
9
+ def self.tablet_name
10
+ name.underscore.sub(/_tablet$/, '')
11
+ end
12
+
13
+ def name
14
+ self.class.tablet_name
15
+ end
16
+
17
+ # Returns general jquery-datatable configuration overrides
18
+ def options
19
+ {}
20
+ end
21
+
22
+ # Determines is user authorized
23
+ def authorize(controller)
24
+ true
25
+ end
26
+
27
+ # Allows to make additional processing before records would be used
28
+ def process(records)
29
+ records
30
+ end
31
+
32
+ # Returns details HTML for the record
33
+ def details(record)
34
+ nil
35
+ end
36
+
37
+ # Returns columns definitions
38
+ def columns
39
+ deduct_columns_from_relation
40
+ end
41
+
42
+ # Returns database relation to fetch data
43
+ def relation(options = {})
44
+ name.camelize.constantize.where(nil)
45
+ end
46
+
47
+ # Returns additional data returned to client
48
+ def payload
49
+ {}
50
+ end
51
+
52
+ private
53
+
54
+ # Returns default columns definititions, deducted from relation
55
+ def deduct_columns_from_relation
56
+ relation.columns.map(&:name).map do |name|
57
+ {
58
+ title: name.humanize.capitalize,
59
+ data: name.to_sym,
60
+ order: name
61
+ }
62
+ end
63
+ end
64
+ end
65
+ end
data/lib/tablets/data.rb CHANGED
@@ -34,7 +34,7 @@ module Tablets
34
34
 
35
35
  # Relation with concretized parameters
36
36
  def concrete_relation
37
- tablet.relation(relation_params, controller)
37
+ tablet.relation(params: relation_params, controller: controller)
38
38
  end
39
39
 
40
40
  # Relation params. Empty hash by default
@@ -3,20 +3,8 @@ module Tablets
3
3
  # Tablets loader
4
4
  # Manages files loading from app tablets directory
5
5
  module Loader
6
- # Unloads tablet
7
- def unload!
8
- @tablets = nil
9
- end
10
-
11
- # Checks if tablet is loading
12
- # Tablets is not loaded only if tablets is nil
13
- def loaded?
14
- !@tablets.nil?
15
- end
16
-
17
6
  # Loads tablets files
18
7
  def load!
19
- @tablets = {}
20
8
  files.each { |file| load file }
21
9
  end
22
10
 
@@ -1,4 +1,4 @@
1
- require 'tablets/tablet'
1
+ require 'tablets/base'
2
2
 
3
3
  module Tablets
4
4
  module Global
@@ -7,18 +7,16 @@ module Tablets
7
7
  module Store
8
8
  extend Forwardable
9
9
 
10
- attr_reader :tablets
11
-
12
10
  def_delegators :tablets, :[]
13
11
 
14
- # Initializes tablet and put tablet into store
15
- #
16
- # Tablets.register(:user) do
17
- # # Tablet configuration.
18
- # end
19
- #
20
- def register(name, &block)
21
- @tablets[name] = Tablets::Tablet.new(name, &block)
12
+ def tablets
13
+ @tablets || {}
14
+ end
15
+
16
+ # put tablet into store
17
+ def register_tablet(name, tablet_class)
18
+ @tablets ||= {}
19
+ @tablets[name] = tablet_class
22
20
  end
23
21
  end
24
22
  end
@@ -20,15 +20,7 @@ module Tablets
20
20
  # Manages tablets loading and cleanup
21
21
  # Also ensures tablets reloading in development environment
22
22
  initializer 'tablets.reloader' do |app|
23
- if app.config.reload_classes_only_on_change
24
- reloader_class.to_prepare(prepend: true) { Tablets.unload! }
25
- else
26
- reloader_class.to_cleanup { Tablets.unload! }
27
- end
28
-
29
- reloader_class.to_prepare do
30
- Tablets.load! unless Tablets.loaded?
31
- end
23
+ reloader_class.to_prepare { Tablets.load! }
32
24
  end
33
25
  end
34
26
  end
@@ -1,8 +1,8 @@
1
1
  module Tablets
2
2
  # Tablets gem version
3
3
  module Version
4
- MAJOR = 1
5
- MINOR = 1
4
+ MAJOR = 2
5
+ MINOR = 0
6
6
  TINY = 0
7
7
  PRE = nil
8
8
 
@@ -12,7 +12,7 @@ module Tablets
12
12
  locals = opts.fetch(:locals, {})
13
13
  initialize_instantly = opts.fetch(:initialize_instantly, false)
14
14
 
15
- Tablets::Renderer.new(Tablets[name], locals, initialize_instantly: initialize_instantly).render(self)
15
+ Tablets::Renderer.new(Tablets[name.to_s].new, locals, initialize_instantly: initialize_instantly).render(self)
16
16
  end
17
17
  end
18
18
  end
data/lib/tablets.rb CHANGED
@@ -13,8 +13,6 @@ end
13
13
 
14
14
  require 'tablets/version'
15
15
 
16
- require 'tablets/tablet'
17
-
18
16
  if defined? Rails
19
17
  require 'tablets/railtie'
20
18
  require 'tablets/engine'
@@ -20,11 +20,12 @@ RSpec.describe Tablets::Data::Processing::Order do
20
20
  context 'simple' do
21
21
  let(:field) { 'field' }
22
22
  let(:direction) { 'DESC' }
23
+ let(:nulls) { 'NULLS LAST' }
23
24
  let(:columns) { [{ order: field }] }
24
25
  let(:values) { [{ column: 0, dir: direction }] }
25
26
 
26
27
  it 'applies order' do
27
- expect(relation).to have_received(:order).with("#{field} #{direction}")
28
+ expect(relation).to have_received(:order).with("#{field} #{direction} #{nulls}")
28
29
  end
29
30
 
30
31
  it 'returns relation' do
@@ -38,7 +39,7 @@ RSpec.describe Tablets::Data::Processing::Order do
38
39
  let(:values) { [{ column: 0 }] }
39
40
 
40
41
  it 'applies order with default direction' do
41
- expect(relation).to have_received(:order).with("#{field} ASC")
42
+ expect(relation).to have_received(:order).with("#{field} ASC NULLS FIRST")
42
43
  end
43
44
 
44
45
  it 'returns relation' do
@@ -49,7 +50,7 @@ RSpec.describe Tablets::Data::Processing::Order do
49
50
  context 'multiple' do
50
51
  let(:orders) do
51
52
  (0..1).map do |index|
52
- { field: "field#{index}", direction: 'DESC' }
53
+ { field: "field#{index}", direction: 'DESC', nulls: 'NULLS LAST' }
53
54
  end
54
55
  end
55
56
  let(:columns) { orders.map { |order| { order: order[:field] } } }
@@ -62,7 +63,7 @@ RSpec.describe Tablets::Data::Processing::Order do
62
63
  it 'applies order' do
63
64
  orders.each do |order|
64
65
  expect(relation).to have_received(:order)
65
- .with("#{order[:field]} #{order[:direction]}")
66
+ .with("#{order[:field]} #{order[:direction]} #{order[:nulls]}")
66
67
  end
67
68
  end
68
69
 
@@ -7,42 +7,6 @@ require 'tablets/global/loader'
7
7
  RSpec.describe Tablets::Global::Loader do
8
8
  subject { Object.new.tap { |object| object.extend(described_class) } }
9
9
 
10
- def self.set_tablets
11
- before do
12
- subject.instance_variable_set(:@tablets, yield)
13
- end
14
- end
15
-
16
- def tablets
17
- subject.instance_variable_get(:@tablets)
18
- end
19
-
20
- describe '#unload!' do
21
- set_tablets { {} }
22
-
23
- before { subject.unload! }
24
-
25
- it 'sets tablets to nil' do
26
- expect(tablets).to be_nil
27
- end
28
- end
29
-
30
- describe '#loaded?' do
31
- context 'if tablets is not nil' do
32
- set_tablets { {} }
33
-
34
- it 'returns true' do
35
- expect(subject.loaded?).to eq(true)
36
- end
37
- end
38
-
39
- context 'if tablets is nil' do
40
- it 'returns false' do
41
- expect(subject.loaded?).to eq(false)
42
- end
43
- end
44
- end
45
-
46
10
  describe '#load!' do
47
11
  let(:files) { %w(file1 file2) }
48
12
  let(:tablets_dir) { 'dir' }
@@ -56,16 +20,10 @@ RSpec.describe Tablets::Global::Loader do
56
20
  allow(subject).to receive(:load)
57
21
  end
58
22
 
59
- before { subject.load! }
60
-
61
- it 'sets tablets to empty hash' do
62
- expect(tablets).to eq({})
63
- end
64
-
65
- it 'loads each file' do
66
- files.each do |file|
67
- expect(subject).to have_received(:load).with(file)
68
- end
23
+ it 'loads files from tablets directory' do
24
+ expect(subject).to receive(:load).with 'file1'
25
+ expect(subject).to receive(:load).with 'file2'
26
+ subject.load!
69
27
  end
70
28
  end
71
29
  end
@@ -7,20 +7,13 @@ RSpec.describe Tablets::Global::Store do
7
7
 
8
8
  describe '#register' do
9
9
  let(:name) { :posts }
10
- let(:block) { proc {} }
11
10
  let(:tablet) { double }
12
11
 
13
12
  before do
14
13
  subject.instance_eval { @tablets = {} }
15
- allow(Tablets::Tablet).to receive(:new)
16
- .with(name, &block).and_return(tablet)
17
14
  end
18
15
 
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
16
+ let!(:result) { subject.register_tablet(name, tablet) }
24
17
 
25
18
  it 'stores tablet' do
26
19
  expect(subject.tablets).to eq(name => tablet)
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ require 'tablets'
4
+
5
+ require 'tablets/base'
6
+
7
+ RSpec.describe Tablets::Base do
8
+ class PostTablet < Tablets::Base; end
9
+
10
+ subject { PostTablet.new }
11
+
12
+ describe '#name' do
13
+ let(:result) { subject.name }
14
+
15
+ it 'returns tablet name' do
16
+ expect(result).to eq('post')
17
+ end
18
+ end
19
+
20
+ describe '#options' do
21
+ let(:result) { subject.options }
22
+
23
+ it 'returns tablet options' do
24
+ expect(result).to eq({})
25
+ end
26
+ end
27
+
28
+ describe '#authorize' do
29
+ let(:result) { subject.authorize(nil) }
30
+
31
+ it 'returns tablet authorization response' do
32
+ expect(result).to eq(true)
33
+ end
34
+ end
35
+
36
+ describe '#process' do
37
+ let(:result) { subject.process([1, 2]) }
38
+
39
+ it 'returns tablet processings' do
40
+ expect(result).to eq([1, 2])
41
+ end
42
+ end
43
+
44
+ describe '#details' do
45
+ let(:result) { subject.details(nil) }
46
+
47
+ it 'returns tablet details' do
48
+ expect(result).to eq(nil)
49
+ end
50
+ end
51
+
52
+ describe '#payload' do
53
+ let(:result) { subject.payload }
54
+
55
+ it 'returns tablet payload' do
56
+ expect(result).to eq({})
57
+ end
58
+ end
59
+
60
+ describe '#tablet_name' do
61
+ let(:result) { PostTablet.tablet_name }
62
+
63
+ it 'returns tablet name' do
64
+ expect(result).to eq('post')
65
+ end
66
+ end
67
+ end
@@ -9,15 +9,16 @@ RSpec.describe Tablets::ViewHelpers do
9
9
 
10
10
  describe '#render_tablet' do
11
11
  let(:name) { :name }
12
- let(:params) { 'params' }
12
+ let(:params) { {} }
13
+ let(:initialize_param) { { initialize_instantly: false } }
13
14
  let(:tablet) { double }
14
15
  let(:renderer) { double }
15
16
  let(:render_result) { 'render_result' }
16
17
 
17
18
  before do
18
- allow(Tablets).to receive(:[]).with(name).and_return(tablet)
19
+ allow(Tablets).to receive_message_chain(:[], :new).and_return(tablet)
19
20
  allow(Tablets::Renderer).to receive(:new)
20
- .with(tablet, params).and_return(renderer)
21
+ .with(tablet, params, initialize_param).and_return(renderer)
21
22
  allow(renderer).to receive(:render)
22
23
  .with(subject).and_return(render_result)
23
24
  end
@@ -25,11 +26,11 @@ RSpec.describe Tablets::ViewHelpers do
25
26
  let!(:result) { subject.render_tablet(name, params) }
26
27
 
27
28
  it 'finds tablet' do
28
- expect(Tablets).to have_received(:[]).with(name)
29
+ expect(Tablets).to have_received(:[]).with(name.to_s)
29
30
  end
30
31
 
31
32
  it 'initializes renderer' do
32
- expect(Tablets::Renderer).to have_received(:new).with(tablet, params)
33
+ expect(Tablets::Renderer).to have_received(:new).with(tablet, params, initialize_param)
33
34
  end
34
35
 
35
36
  it 'renders in current view context' do
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tablets
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
+ - Ramunas Cvirka
7
8
  - Yevhen Shemet
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2016-08-11 00:00:00.000000000 Z
12
+ date: 2018-03-19 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rails
@@ -96,7 +97,7 @@ dependencies:
96
97
  version: 0.30.1
97
98
  description:
98
99
  email:
99
- - yevhene@gmail.com
100
+ - rcvirka@zenedge.com
100
101
  executables: []
101
102
  extensions: []
102
103
  extra_rdoc_files: []
@@ -113,6 +114,7 @@ files:
113
114
  - app/views/tablets/_tablet.html.erb
114
115
  - config/routes.rb
115
116
  - lib/tablets.rb
117
+ - lib/tablets/base.rb
116
118
  - lib/tablets/data.rb
117
119
  - lib/tablets/data/processing/base.rb
118
120
  - lib/tablets/data/processing/filter.rb
@@ -125,7 +127,6 @@ files:
125
127
  - lib/tablets/global/store.rb
126
128
  - lib/tablets/railtie.rb
127
129
  - lib/tablets/renderer.rb
128
- - lib/tablets/tablet.rb
129
130
  - lib/tablets/utils/config.rb
130
131
  - lib/tablets/utils/search_condition_builder.rb
131
132
  - lib/tablets/version.rb
@@ -139,7 +140,7 @@ files:
139
140
  - spec/lib/tablets/global/loader_spec.rb
140
141
  - spec/lib/tablets/global/store_spec.rb
141
142
  - spec/lib/tablets/renderer_spec.rb
142
- - spec/lib/tablets/tablet_spec.rb
143
+ - spec/lib/tablets/tablets_base_spec.rb
143
144
  - spec/lib/tablets/utils/config_spec.rb
144
145
  - spec/lib/tablets/utils/search_condition_builder_spec.rb
145
146
  - spec/lib/tablets/view_helpers_spec.rb
@@ -164,22 +165,22 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
165
  version: '0'
165
166
  requirements: []
166
167
  rubyforge_project:
167
- rubygems_version: 2.4.8
168
+ rubygems_version: 2.5.2
168
169
  signing_key:
169
170
  specification_version: 4
170
171
  summary: Wrapper around jquery-datatables.
171
172
  test_files:
173
+ - spec/lib/tablets/data/processing/paginate_spec.rb
172
174
  - spec/lib/tablets/data/processing/base_spec.rb
173
175
  - spec/lib/tablets/data/processing/filter_spec.rb
174
176
  - spec/lib/tablets/data/processing/order_spec.rb
175
- - spec/lib/tablets/data/processing/paginate_spec.rb
176
177
  - spec/lib/tablets/data/query_spec.rb
178
+ - spec/lib/tablets/view_helpers_spec.rb
177
179
  - spec/lib/tablets/global/configurator_spec.rb
178
- - spec/lib/tablets/global/loader_spec.rb
179
180
  - spec/lib/tablets/global/store_spec.rb
181
+ - spec/lib/tablets/global/loader_spec.rb
182
+ - spec/lib/tablets/tablets_base_spec.rb
180
183
  - spec/lib/tablets/renderer_spec.rb
181
- - spec/lib/tablets/tablet_spec.rb
182
- - spec/lib/tablets/utils/config_spec.rb
183
184
  - spec/lib/tablets/utils/search_condition_builder_spec.rb
184
- - spec/lib/tablets/view_helpers_spec.rb
185
+ - spec/lib/tablets/utils/config_spec.rb
185
186
  - spec/spec_helper.rb
@@ -1,86 +0,0 @@
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
- # By default deduct columns from relation
40
- def columns
41
- call(:columns) { deduct_columns_from_relation }
42
- end
43
-
44
- # Returns database relation to fetch data
45
- # By default tries to deduct class from tablet name
46
- def relation(params = {}, controller = nil)
47
- if defined? @name.singularize.camelize.constantize
48
- call(:relation, params, controller) do
49
- @name.camelize.constantize.where(nil)
50
- end
51
- else
52
- call(:relation, params, controller)
53
- end
54
- end
55
-
56
- # Returns additional data returned to client
57
- def payload
58
- call(:payload) { {} }
59
- end
60
-
61
- # Checks if config has callback with specified name
62
- def has?(name)
63
- @config.has?(name)
64
- end
65
-
66
- private
67
-
68
- # Returns default columns definititions, deducted from relation
69
- def deduct_columns_from_relation
70
- relation.columns.map(&:name).map do |name|
71
- {
72
- title: name.humanize.capitalize,
73
- data: name.to_sym,
74
- order: name
75
- }
76
- end
77
- end
78
-
79
- # Calls callback and clarifies error message on error
80
- def call(callback, *params, &block)
81
- @config.call(callback, *params, &block)
82
- rescue ArgumentError
83
- raise ArgumentError, "Please define #{callback} for '#{name}' tablet."
84
- end
85
- end
86
- end
@@ -1,42 +0,0 @@
1
- require 'spec_helper'
2
-
3
- require 'tablets'
4
-
5
- require 'tablets/tablet'
6
-
7
- RSpec.describe Tablets::Tablet do
8
- let(:name) { 'example' }
9
- let(:block) { proc {} }
10
-
11
- subject { described_class.new(name, &block) }
12
-
13
- def self.define(callback, value)
14
- let(:block) do
15
- proc { send(callback) { value } }
16
- end
17
- end
18
-
19
- context '#relation' do
20
- context 'if configured' do
21
- define(:relation, 'relation')
22
-
23
- let!(:result) { subject.relation }
24
-
25
- it 'return column configuration' do
26
- expect(result).to eq('relation')
27
- end
28
- end
29
- end
30
-
31
- context '#columns' do
32
- context 'if configured' do
33
- define(:columns, 'columns')
34
-
35
- let!(:result) { subject.columns }
36
-
37
- it 'return column configuration' do
38
- expect(result).to eq('columns')
39
- end
40
- end
41
- end
42
- end