iquest-simple_table 0.3.6 → 0.4.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: 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