iquest-simple_table 0.3.6 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9605388d187db1edcbc45d873ce710cbe8ae4c0b
4
- data.tar.gz: 739f74b35c801f11e41f95ad1083f37fea20f360
3
+ metadata.gz: 45e5c0239f2c37302736ee01e5bd1465eea65bf2
4
+ data.tar.gz: b9172276ac0091318da04c4be5ff4a131f195c87
5
5
  SHA512:
6
- metadata.gz: 1d61e21c206fbfab19317fad3d67c681dc284813815615db37cf8e0635cd99c5e4701a0b90b39499d33c047c4900ee6c092dfef17961ea749a5be4d35a2bcd7c
7
- data.tar.gz: 8fa682beeef5041e90fb3e73e787833f0bb79108f0dacf048aba5528ef1a303fc4aae5830e63691fd8649167254b6bc60a023d76e93ccdc2dd97471ed5c403ac
6
+ metadata.gz: a5290739813210936128ea1be2e03298e431d74b9b973ed1745ed75cdf05da38457165ee89040f10a6ce51107981e54bd1bb25abd59a01983a3c547cda539eda
7
+ data.tar.gz: ec02416131cbafd96908be1eddd0fd968c945bfd062497db3093fdbd45e6412ff8eea1c3f390b28dbb426bd36d24761872e2ca2941ee27fac26b666fc2a78db5
data/.rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ inherit_gem:
2
+ relaxed-rubocop: .rubocop.yml
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.1.5
1
+ 2.2.7
@@ -0,0 +1 @@
1
+ 2.2.2
data/bench/bench.rb ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require 'bundler/inline'
6
+ rescue LoadError => e
7
+ $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
8
+ raise e
9
+ end
10
+
11
+ require 'optparse'
12
+
13
+ options = {}
14
+ OptionParser.new do |opts|
15
+ opts.banner = "Usage: bench.rb [options]"
16
+
17
+ opts.on("-m", "--[no-]mem", "Memory profile") do |v|
18
+ options[:mem] = v
19
+ end
20
+ opts.on("-b", "--[no-]bench", "Benchmark IPS") do |v|
21
+ options[:bench] = v
22
+ end
23
+ opts.on("-t", "--[no-]time", "Method timing") do |v|
24
+ options[:time] = v
25
+ end
26
+ end.parse!
27
+
28
+ gemfile(true) do
29
+ source 'https://rubygems.org'
30
+
31
+ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
32
+
33
+ # Activate the gem you are reporting the issue against.
34
+ gem 'rails', '5.2.0'
35
+ gem 'activerecord', '5.2.0'
36
+ gem 'benchmark-ips'
37
+ gem 'kaminari'
38
+ gem 'memory_profiler'
39
+ gem 'ransack', '1.8.8', require: false
40
+ gem 'iquest-simple_table', path: '../', require: false
41
+ gem 'timeasure'
42
+ end
43
+
44
+ require 'rails/all'
45
+
46
+ class BenchApp < Rails::Application
47
+ config.root = __dir__
48
+ config.session_store :cookie_store, key: 'cookie_store_key'
49
+ secrets.secret_key_base = 'secret_key_base'
50
+
51
+ config.logger = Logger.new($stdout)
52
+ Rails.logger = config.logger
53
+ end
54
+
55
+ require 'iquest/simple_table'
56
+
57
+ class ApplicationController < ActionController::Base
58
+ layout false
59
+ prepend_view_path('templates')
60
+ end
61
+
62
+ class Foo
63
+ include ActiveModel::Model
64
+ ATTRIBUTES = %i(a b c d e f g h).freeze
65
+ attr_accessor *ATTRIBUTES
66
+ delegate :each, :map, to: :attributes
67
+
68
+ def attributes
69
+ ATTRIBUTES.map { |a| send(a) }
70
+ end
71
+ end
72
+
73
+ def render(template, **assigns)
74
+ ApplicationController.render(
75
+ template: template.to_s,
76
+ layout: nil,
77
+ locals: assigns
78
+ )
79
+ end
80
+
81
+ def memory_profile(title)
82
+ report = MemoryProfiler.report(top: 10, ingnore_files: /memory_profiler/) do
83
+ yield
84
+ end
85
+ puts '=' * 80
86
+ puts title
87
+ puts '=' * 80
88
+ report.pretty_print
89
+ end
90
+
91
+ today = Date.today
92
+ now = Time.now
93
+ collection = Array.new(100) { Foo.new(a: 0, b: 1, c: 2, d: 3, e: 4, f: 5, g: today, h: now) }
94
+ table = Kaminari.paginate_array(collection).page(1).per(100)
95
+
96
+ if options[:mem]
97
+ memory_profile 'table' do
98
+ render 'table', table: table
99
+ end
100
+
101
+ memory_profile 'simple_table' do
102
+ render 'simple_table', table: table
103
+ end
104
+ end
105
+
106
+ if options[:bench]
107
+ Benchmark.ips do |x|
108
+ x.report('table') { render 'table', table: table }
109
+ x.report('simple_table') { render 'simple_table', table: table }
110
+
111
+ x.compare!
112
+ end
113
+ end
114
+
115
+ if options[:time]
116
+ require 'timeasure'
117
+
118
+ module Iquest
119
+ module SimpleTable
120
+ class TableBuilder
121
+ include Timeasure
122
+ tracked_instance_methods :to_s
123
+ tracked_private_instance_methods :render_table_row, :attr_class
124
+ end
125
+ end
126
+ end
127
+
128
+ require 'pp'
129
+
130
+ Timeasure::Profiling::Manager.prepare
131
+ render 'simple_table', table: table
132
+ report = Timeasure::Profiling::Manager.export
133
+ report.each do |item|
134
+ pp item
135
+ end
136
+ end
File without changes
@@ -0,0 +1,10 @@
1
+ <%= simple_table_for table do |t|
2
+ t.column :a
3
+ t.column :b
4
+ t.column :c
5
+ t.column :d
6
+ t.column :e
7
+ t.column :f
8
+ t.column :g
9
+ t.column :h
10
+ end %>
@@ -0,0 +1,15 @@
1
+
2
+ <table>
3
+ <% table.each do |row| %>
4
+ <tr>
5
+ <td><%= row.a %></td>
6
+ <td><%= row.b %></td>
7
+ <td><%= row.c %></td>
8
+ <td><%= row.d %></td>
9
+ <td><%= row.e %></td>
10
+ <td><%= row.f %></td>
11
+ <td><%= l(row.g) %></td>
12
+ <td><%= l(row.h) %></td>
13
+ </tr>
14
+ <% end %>
15
+ </table>
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Iquest::SimpleTable::VERSION
9
9
  spec.authors = ["Pavel Dusanek"]
10
10
  spec.email = ["dusanek@iquest.cz"]
11
- spec.description = %q{Simple table helper}
12
- spec.summary = %q{Simple table helper, taht supports filtering through Ransack}
11
+ spec.description = "Simple table helper"
12
+ spec.summary = "Simple table helper, taht supports filtering through Ransack"
13
13
  spec.homepage = "https://github.com/iquest/iquest-simple_table"
14
14
  spec.license = "MIT"
15
15
 
@@ -21,4 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_runtime_dependency 'ransack_simple_form', '>= 0.1.0'
22
22
  spec.add_development_dependency "bundler", "~> 1.3"
23
23
  spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "relaxed-rubocop"
25
+ spec.add_development_dependency "rubocop"
24
26
  end
@@ -1,12 +1,11 @@
1
1
  module Iquest
2
2
  module SimpleTable
3
3
  module AttributeDescription
4
-
5
4
  def human_attribute_description(attribute, options = {})
6
5
  parts = attribute.to_s.split(".")
7
6
  attribute = parts.pop
8
7
  namespace = parts.join("/") unless parts.empty?
9
- attributes_scope = "#{self.i18n_scope}.descriptions"
8
+ attributes_scope = "#{i18n_scope}.descriptions"
10
9
 
11
10
  if namespace
12
11
  defaults = lookup_ancestors.map do |klass|
@@ -24,7 +23,6 @@ module Iquest
24
23
  options[:default] = ''
25
24
  I18n.translate(defaults.shift, options)
26
25
  end
27
-
28
26
  end
29
27
  end
30
- end
28
+ end
@@ -8,6 +8,19 @@ module Iquest
8
8
  delegate :sort_link, :search_form_for, to: :parent
9
9
  delegate :polymorphic_path, :polymorphic_url, to: :parent
10
10
  delegate :l, :t, :dom_id, to: :parent
11
+ delegate :render, :render_to_string, to: :parent
12
+ CLASS_DELIMITER = ' '.freeze
13
+ EMPTY_STRING = ''.freeze
14
+ DEFAULT_FORMATTER = ->(value) do
15
+ case value
16
+ when Time
17
+ l(value)
18
+ when Date
19
+ l(value)
20
+ else
21
+ value
22
+ end
23
+ end
11
24
 
12
25
  def initialize(parent, collection_or_search, options = {})
13
26
  @parent = parent
@@ -18,208 +31,146 @@ module Iquest
18
31
  elsif collection_or_search.is_a?(ActiveRecord::Relation) || collection_or_search.is_a?(ActiveRecord::AssociationRelation)
19
32
  @collection = collection_or_search
20
33
  @klass = @collection.klass
21
- elsif collection_or_search.is_a?(Array) && (search = collection_or_search.detect {|o| o.is_a?(Ransack::Search)})
34
+ elsif collection_or_search.is_a?(Array) && (search = collection_or_search.detect { |o| o.is_a?(Ransack::Search) })
22
35
  @search = search
23
36
  @collection = search.result
24
37
  @klass = @collection.klass
25
- options[:search_url] ||= polymorphic_path(collection_or_search.map {|o| o.is_a?(Ransack::Search) ? o.klass : o})
26
- elsif collection_or_search.is_a?(Array) && (collection = collection_or_search.detect {|o| o.is_a?(ActiveRecord::Relation) || o.is_a?(ActiveRecord::AssociationRelation)})
38
+ options[:search_url] ||= polymorphic_path(collection_or_search.map { |o| o.is_a?(Ransack::Search) ? o.klass : o })
39
+ elsif collection_or_search.is_a?(Array) && (collection = collection_or_search.detect { |o| o.is_a?(ActiveRecord::Relation) || o.is_a?(ActiveRecord::AssociationRelation) })
27
40
  @collection = collection
28
41
  @klass = @collection.klass
29
42
  elsif collection_or_search.is_a?(Array) && (collection_or_search.any? || options[:class])
30
43
  @collection = collection_or_search
31
44
  @klass = options[:class] || collection_or_search.first.class
32
- else
45
+ else
33
46
  raise TypeError, 'ActiveRecord::Relation, ActiveRecord::AssociationRelation, Ransack::Search or Array of ActiveModel like objects expected'
34
47
  end
35
48
  apply_pagination
36
- #draper
49
+ # draper
37
50
  @collection = @collection.decorate if @collection.respond_to?(:decorate)
38
- options[:search_url] ||= polymorphic_path(@klass) rescue NoMethodError
51
+ options[:search_url] ||= begin
52
+ polymorphic_path(@klass)
53
+ rescue NoMethodError
54
+ nil
55
+ end
39
56
  @options = options
40
57
  @table_id = "table_#{@klass}".pluralize.parameterize
41
58
  @columns = {}.with_indifferent_access
42
59
  @actions = []
43
60
  @collection_actions = []
44
- @search_input_default_options = {label: false, placeholder: false}.with_indifferent_access
61
+ @search_input_default_options = { label: false, placeholder: false }.with_indifferent_access
62
+ @attr_classes = {}
45
63
  end
46
64
 
47
65
  def column(*args, &block)
48
66
  attr = args.first
49
67
  options = args.extract_options!
50
- search = options.delete(:search)
68
+ search = options.delete(:search)
51
69
  @columns[attr] = options
52
70
  @columns[attr][:label] ||= column_label(attr)
53
- #iniciaizce search options
71
+ # iniciaizce search options
54
72
  if search.is_a?(Symbol) || search.is_a?(String)
55
- @columns[attr][:search] = {search.to_sym => {}}
73
+ @columns[attr][:search] = { search.to_sym => {} }
56
74
  elsif search.is_a? Array
57
- @columns[attr][:search] = search.inject({}) {|h, s| h[s.to_sym] = {}; h}
75
+ @columns[attr][:search] = search.each_with_object({}) { |s, h| h[s.to_sym] = {}; }
58
76
  elsif search.is_a? Hash
59
77
  @columns[attr][:search] = search
60
78
  end
61
- @columns[attr][:formatter] ||= block if block_given?
62
- @columns[attr][:sort] ||= attr.to_s.tr('.','_') unless @columns[attr][:sort] == false #sort link attr
79
+ @columns[attr][:formatter] ||= block_given? ? block : DEFAULT_FORMATTER
80
+ @columns[attr][:sort] ||= attr.to_s.tr('.', '_') unless @columns[attr][:sort] == false # sort link attr
63
81
  @columns[attr][:html] ||= {}
82
+ @columns[attr][:html][:class] = @columns[attr][:html][:class].join(CLASS_DELIMITER) if @columns[attr][:html][:class].is_a?(Array)
83
+ @columns[attr][:html][:class] ||= ''
64
84
  end
65
85
 
66
86
  def action(*args, &block)
67
- action = args.first
87
+ _action = args.first
68
88
  options = args.extract_options!
69
89
  options[:proc] = block if block_given?
70
90
  @actions << options
71
91
  end
72
92
 
73
- def collection_action(*args, &block)
93
+ def collection_action(*args)
74
94
  action = args.first
75
95
  if action.is_a? String
76
96
  @collection_actions << action
77
97
  elsif block_given?
78
- @collection_actions << block.call
79
- end
98
+ @collection_actions << yield
99
+ end
80
100
  end
81
101
 
82
- def new_link(*args, &block)
102
+ def new_link(*_args)
83
103
  ActiveSupport::Deprecation.warn("Iquest::SimpleTable#new_link does nothing. Use collection_action")
84
104
  end
85
105
 
86
- def search_link(*args, &block)
106
+ def search_link(*_args, &block)
87
107
  @search_button = block if block_given?
88
108
  end
89
109
 
90
- def reset_link(*args, &block)
110
+ def reset_link(*_args, &block)
91
111
  @reset_button = block if block_given?
92
112
  end
93
113
 
114
+ WRAPPER_TEMPLATE = '<div class="filter-table-block">
115
+ <%= content %>
116
+ <div class="paginate-block"><%= paginate @collection if @collection.respond_to?(:current_page) %></div>
117
+ <div class="totals-block"><%= page_entries_info @collection, entry_name: @klass.model_name.human if @collection.respond_to?(:current_page) %></div>
118
+ </div>'.freeze
119
+ WRAPPER_ERB = ERB.new(WRAPPER_TEMPLATE)
120
+
94
121
  def to_s
95
- if @search
96
- content_tag :div, '', class: 'filter-table-block' do
97
- render_table_with_search
98
- end
99
- else
100
- content_tag :div, '', class: 'filter-table-block' do
101
- render_table_without_search
102
- end
103
- end
122
+ content = render_table
123
+ WRAPPER_ERB.result(binding).html_safe
104
124
  end
105
125
 
106
126
  private
107
- def render_table_without_search
108
- table = content_tag :table, id: @table_id, class: @options[:html][:class] << %w(table table-hover table-striped) do
109
- render_table_header + render_table_body + render_table_footer
110
- end
111
-
112
- out = if @options[:responsive]
113
- content_tag :div, class: 'table-responsive' do
114
- table
115
- end
116
- else
117
- table
118
- end
119
-
120
- out + render_pagination + render_footer_actions
121
- end
122
127
 
128
+ TABLE_TEMPLATE = '
129
+ <% if @options[:responsive] %><div class="table-responsive"><%end%>
130
+ <table id="<%= @table_id %>" class="<%= @options[:html][:class].join(CLASS_DELIMITER) %> table table-hover table-striped">
131
+ <thead>
132
+ <tr class="labels">
133
+ <th class="collection-actions"><%= @collection_actions.join %></th>
134
+ <% columns.each do |attr, options| %>
135
+ <%= content_tag :th, class: options[:class], data: options[:data] do
136
+ render_label(attr)
137
+ end %>
138
+ <% end %>
139
+ <% if @search %>
140
+ <%= render_search_inputs %>
141
+ <% end %>
142
+ </tr>
143
+ </thead>
144
+ <tbody class="rowlink" data-link="row" data-target="a.rowlink">
145
+ <% collection.each do |item| %>
146
+ <%= render_table_row(item) %>
147
+ <% end %>
148
+ </tbody>
149
+ <tfoot class=""><tr class=""></tr></tfoot>
150
+ </table>
151
+ <% if @options[:responsive] %></div><%end%>
152
+ '.freeze
153
+ TABLE_ERB = ERB.new(TABLE_TEMPLATE)
123
154
  include RansackSimpleForm::FormHelper
124
155
 
125
- def render_table_with_search
126
- ransack_simple_form_for @search, url: @options[:search_url] do |f|
127
- @search_form = f
128
- render_table_without_search
129
- end
130
- end
131
-
132
- def render_table_header
133
- content_tag :thead, class: 'header' do
134
- render_column_labels + render_search_inputs
135
- end
136
- end
137
-
138
- def render_column_labels
139
- content_tag :tr, class:'labels' do
140
- rendered_columns = columns.map do |col, opts|
141
- render_column_label(col)
142
- end.join.html_safe
143
- render_collection_actions + rendered_columns
144
- end
145
- end
146
-
147
- def render_collection_actions
148
- content_tag :th, class:'collection-actions' do
149
- @collection_actions.join.html_safe
150
- end
151
- end
152
-
153
- def render_search_inputs
154
- return '' unless @search
155
- content_tag :tr, class:'filters' do
156
- rendered_columns = columns.map do |col, opts|
157
- render_column_search_inputs(col, opts)
158
- end.join.html_safe
159
- render_buttons + rendered_columns
160
- end
161
- end
162
-
163
- def render_column_search_inputs(column, options)
164
- content_tag :th, class: options[:class], data: options[:data] do
165
- if options[:search]
166
- options[:search].map do |search, options|
167
- render_search_input(search, options)
168
- end.join.html_safe
169
- end
170
- end
171
- end
172
-
173
- def render_search_input(search, options = {})
174
- input_options = @search_input_default_options.merge(options).symbolize_keys
175
- search_form.input search.dup, input_options
176
- end
177
-
178
- def render_buttons
179
- content_tag :th, class:'search-action' do
180
- out = content_tag :div, class:'btn-group' do
181
- link_to(t('simple_table.reset', default: 'reset').html_safe, '?' , class: 'search-reset btn btn-default') +
182
- search_form.button( :submit, t('simple_table.search', default: 'search').html_safe, class: 'search-button btn btn-default')
156
+ def render_table
157
+ if @search
158
+ ransack_simple_form_for @search, url: @options[:search_url] do |f|
159
+ @search_form = f
160
+ TABLE_ERB.result(binding).html_safe
183
161
  end
184
- # FIXME change link_to url
185
- end
186
- end
187
-
188
- def render_table_body
189
- content_tag :tbody, class: 'rowlink', data: {link: 'row', target: 'a.rowlink'} do
190
- collection.map do |item|
191
- render_table_row(item)
192
- end.join.html_safe
193
- end
194
- end
195
-
196
- def render_table_row(item)
197
- row_id = "row_#{dom_id(item)}" rescue nil
198
- content_tag :tr, id: row_id do
199
- rendered_columns = columns.map do |col|
200
- render_value_cell(col, item)
201
- end.join.html_safe
202
- render_actions(item) + rendered_columns
203
- end
204
- end
205
-
206
-
207
- def render_column_label(column)
208
- options = @columns[column]
209
-
210
- content_tag :th, class: options[:class], data: options[:data] do
211
- render_label(column)
162
+ else
163
+ TABLE_ERB.result(binding).html_safe
212
164
  end
213
165
  end
214
166
 
215
- def render_label(column)
216
- attr = column
167
+ def render_label(attr)
217
168
  options = @columns[attr]
218
169
  label = options[:label] || attr.to_s
219
- sort = options[:sort]
170
+ sort = options[:sort]
220
171
  if @search && sort
221
172
  sort_attr = attr
222
- sort_options = {}
173
+ sort_options = {}
223
174
  if sort.is_a?(Hash)
224
175
  sort_attr = sort.keys.first
225
176
  sort_options = sort[sort_attr]
@@ -234,130 +185,132 @@ module Iquest
234
185
  end
235
186
  end
236
187
 
237
- def render_value_cell(*args)
238
- col = args.first
239
- attr = col.first
240
- options = col.second
241
- obj = args.second
242
- value = get_value(attr, obj)
243
- formatter = options[:formatter]
244
- cell_value = render_value(obj, value, &formatter)
245
- cell_classes = []
246
- cell_classes << "rowlink-skip" if include_link?(cell_value)
247
- cell_classes << "#{options[:html][:class]}"
248
- content_tag :td, class: cell_classes do
249
- "#{cell_value}".html_safe
250
- end
251
- end
252
-
253
- def get_value(attr, obj)
254
- if attr.is_a? Symbol
255
- obj.try(attr)
256
- elsif attr.is_a? String
257
- attr.split('.').inject(obj, :try)
188
+ def render_search_inputs
189
+ return EMPTY_STRING unless @search
190
+ content_tag :tr, class: 'filters' do
191
+ rendered_columns = columns.map do |col, opts|
192
+ render_column_search_inputs(col, opts)
193
+ end.join.html_safe
194
+ render_buttons + rendered_columns
258
195
  end
259
196
  end
260
197
 
261
- def include_link?(string)
262
- string.try(:include?, '<a')
263
- end
264
-
265
- def render_value(*args, &block)
266
- object = args.first
267
- value = args.second
268
- if block_given?
269
- case block.arity
270
- when 1
271
- block.call(value)
272
- when 2
273
- block.call(object, value)
274
- else
275
- block.call
198
+ def render_column_search_inputs(_column, options)
199
+ content_tag :th, class: options[:class], data: options[:data] do
200
+ if options[:search]
201
+ options[:search].map do |search, opts|
202
+ render_search_input(search, opts)
203
+ end.join.html_safe
276
204
  end
277
- else
278
- format_value(value)
279
205
  end
280
-
281
206
  end
282
207
 
283
- def format_value(value)
284
- case value
285
- when Time
286
- l(value)
287
- when Date
288
- l(value)
289
- else
290
- value
291
- end
208
+ def render_search_input(search, options = {})
209
+ input_options = @search_input_default_options.merge(options).symbolize_keys
210
+ search_form.input search.dup, input_options
292
211
  end
293
212
 
294
- def render_actions(item)
295
- content_tag :td, class: 'rowlink-skip' do
296
- @actions.map do |action|
297
- render_action(item, action)
298
- end.join.html_safe
299
- end
300
- end
213
+ BUTTONS_TEMPLATE = %q(<th class="search-action"><div class="btn-group">
214
+ <%= link_to(t('simple_table.reset', default: 'reset').html_safe, '?', class: 'search-reset btn btn-default') %>
215
+ <%= search_form.button( :submit, t('simple_table.search', default: 'search').html_safe, class: 'search-button btn btn-default') %>
216
+ </div></th>).freeze # FIXME change link_to url
217
+ BUTTONS_ERB = ERB.new(BUTTONS_TEMPLATE)
301
218
 
302
- def render_action(*args)
303
- obj = args.first
304
- options = args.extract_options!
305
- options[:proc].call(obj) if options[:proc].is_a? Proc
306
- end
219
+ def render_buttons
220
+ BUTTONS_ERB.result(binding).html_safe
221
+ end
222
+
223
+ ROWLINK_SKIP = 'rowlink-skip'.freeze
224
+ TR_TEMPLATE = '<tr id="<%= row_id %>"><%= actions %>
225
+ <% columns.each do |attr, options| %>
226
+ <%
227
+ options = columns[attr]
228
+ value = get_value(attr, object)
229
+ html_class = options[:html][:class]
230
+ html_class << " #{ROWLINK_SKIP}" if include_link?(value)
231
+ %>
232
+ <td class="<%= html_class %>"><%= value %></td>
233
+ <% end %>
234
+ </tr>'.freeze
235
+ TR_ERB = ERB.new(TR_TEMPLATE)
236
+
237
+ def render_table_row(object)
238
+ row_id = begin
239
+ "row_#{dom_id(object)}"
240
+ rescue StandardError
241
+ nil
242
+ end
243
+ actions = render_actions(object)
244
+ TR_ERB.result(binding).html_safe
245
+ end
246
+
247
+ METHOD_DELIMITER = '.'.freeze
307
248
 
308
- def render_table_footer
309
- content_tag :tfoot, class: '' do
310
- content_tag :tr, class: '' do
311
- end
249
+ def get_value(attr, obj)
250
+ value = if attr.is_a? Symbol
251
+ obj.send(attr) if obj.respond_to?(attr)
252
+ elsif attr.is_a? String
253
+ attr.split(METHOD_DELIMITER).inject(obj, :try)
254
+ end
255
+ formatter = @columns[attr][:formatter] || DEFAULT_FORMATTER
256
+ case formatter.arity
257
+ when 1
258
+ parent.instance_exec value, &formatter
259
+ when 2
260
+ parent.instance_exec obj, value, &formatter
261
+ else
262
+ parent.instance_exec(&formatter)
312
263
  end
313
264
  end
314
265
 
315
- def render_pagination
316
- content_tag :div, '', class: 'paginate-block' do
317
- paginate @collection if @collection.respond_to?(:current_page)
318
- end
319
-
320
- end
266
+ LINK_PATTERN = '<a'.freeze
321
267
 
322
- def render_footer_actions
323
- content_tag :div, '', class: 'totals-block' do
324
- page_entries_info @collection, entry_name: @klass.model_name.human if @collection.respond_to?(:current_page)
325
- end
268
+ def include_link?(string)
269
+ return false unless string.is_a?(String)
270
+ string.include?(LINK_PATTERN)
326
271
  end
327
272
 
328
- private
329
- def column_class(col)
273
+ ACTIONS_TEMPLATE = '<td class="rowlink-skip">
274
+ <% @actions.each do |action|
275
+ <%= options[:proc].call(obj) if options[:proc].is_a? Proc %>
276
+ </td>'
330
277
 
278
+ def render_actions(item)
279
+ content_tag :td, class: 'rowlink-skip' do
280
+ @actions.map do |action|
281
+ render_action(item, action)
282
+ end.join.html_safe
283
+ end
331
284
  end
332
285
 
333
- def column_value(col, obj)
334
- col.to_s.split('.').inject(obj, :try)
286
+ def render_action(obj, **options)
287
+ options[:proc].call(obj) if options[:proc].is_a? Proc
335
288
  end
336
289
 
337
- def column_label(attr)
290
+ def column_label(attr)
338
291
  if attr_class(attr).respond_to?(:human_attribute_name)
339
292
  attr_class(attr).try(:human_attribute_name, attr)
340
293
  elsif @search
341
- Ransack::Translate.attribute(attr.to_s.tr('.','_'), context: @search.context)
294
+ Ransack::Translate.attribute(attr.to_s.tr(METHOD_DELIMITER, '_'), context: @search.context)
342
295
  else
343
296
  attr.to_s.humanize
344
297
  end
345
- end
298
+ end
346
299
 
347
300
  def description(attr)
348
- if attr_class(attr).respond_to?(:human_attribute_description)
349
- description = attr_class(attr).try(:human_attribute_description, attr)
350
- end
301
+ return ''.html_safe unless attr_class(attr).respond_to?(:human_attribute_description)
302
+ description = attr_class(attr).try(:human_attribute_description, attr)
351
303
  if description.present?
352
304
  "<div class=\"description\">#{description}</div>".html_safe
353
305
  else
354
- "".html_safe
306
+ ''.html_safe
355
307
  end
356
308
  end
357
309
 
358
310
  def attr_class(attr)
359
- attr.to_s.split('.')[0..-2].inject(@klass) {|klass, assoc| klass.try(:reflect_on_association, assoc).try(:klass)}
360
- end
311
+ return @attr_classes[attr] if @attr_classes.key?(attr)
312
+ @attr_classes[attr] ||= attr.to_s.split(METHOD_DELIMITER)[0..-2].inject(@klass) { |klass, assoc| klass.try(:reflect_on_association, assoc).try(:klass) }
313
+ end
361
314
 
362
315
  def column_count
363
316
  @columns.count
@@ -372,7 +325,6 @@ module Iquest
372
325
  def search_action
373
326
  :get
374
327
  end
375
-
376
328
  end
377
329
  end
378
330
  end
@@ -1,7 +1,7 @@
1
1
  module Iquest
2
2
  module SimpleTable
3
3
  module TableHelper
4
- def simple_table_for(*args, &block)
4
+ def simple_table_for(*args)
5
5
  collection = args.first
6
6
  opts = args.extract_options!
7
7
 
@@ -17,4 +17,4 @@ module Iquest
17
17
  end
18
18
  end
19
19
  end
20
- end
20
+ end
@@ -1,5 +1,5 @@
1
1
  module Iquest
2
2
  module SimpleTable
3
- VERSION = '0.3.6'
3
+ VERSION = '0.4.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iquest-simple_table
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.6
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Pavel Dusanek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-30 00:00:00.000000000 Z
11
+ date: 2018-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ransack_simple_form
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: relaxed-rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  description: Simple table helper
56
84
  email:
57
85
  - dusanek@iquest.cz
@@ -60,11 +88,17 @@ extensions: []
60
88
  extra_rdoc_files: []
61
89
  files:
62
90
  - ".gitignore"
91
+ - ".rubocop.yml"
63
92
  - ".ruby-version"
64
93
  - Gemfile
65
94
  - LICENSE.txt
66
95
  - README.md
67
96
  - Rakefile
97
+ - bench/.ruby-version
98
+ - bench/bench.rb
99
+ - bench/templates/kaminari/_paginator.html.erb
100
+ - bench/templates/simple_table.html.erb
101
+ - bench/templates/table.html.erb
68
102
  - config/locale/en.yml
69
103
  - iquest-simple_table.gemspec
70
104
  - lib/iquest/simple_table.rb
@@ -92,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
126
  version: '0'
93
127
  requirements: []
94
128
  rubyforge_project:
95
- rubygems_version: 2.2.2
129
+ rubygems_version: 2.4.5.2
96
130
  signing_key:
97
131
  specification_version: 4
98
132
  summary: Simple table helper, taht supports filtering through Ransack