Class: Effective::TableBuilder

Inherits:
Object
  • Object
show all
Defined in:
app/models/effective/table_builder.rb

Constant Summary collapse

FILTER_PARAMETERS =
[:password, :password_confirmation, :status_steps, :wizard_steps, :token, :created_at, :updated_at]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(object, template, options = {}, &block) ⇒ TableBuilder

Returns a new instance of TableBuilder.



15
16
17
18
19
20
21
22
23
24
# File 'app/models/effective/table_builder.rb', line 15

def initialize(object, template, options = {}, &block)
  raise('resource must be an ActiveRecord::Base') unless object.is_a?(ActiveRecord::Base)

  @object = object
  @template = template
  @options = options

  @rows = {}
  @content_fors = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, **kwargs, &block) ⇒ Object

Call default_row for any form field



114
115
116
# File 'app/models/effective/table_builder.rb', line 114

def method_missing(method, *args, **kwargs, &block)
  default_row(args[0], **kwargs, &block)
end

Instance Attribute Details

#content_forsObject

Returns the value of attribute content_fors.



11
12
13
# File 'app/models/effective/table_builder.rb', line 11

def content_fors
  @content_fors
end

#objectObject

Returns the value of attribute object.



7
8
9
# File 'app/models/effective/table_builder.rb', line 7

def object
  @object
end

#optionsObject

Returns the value of attribute options.



7
8
9
# File 'app/models/effective/table_builder.rb', line 7

def options
  @options
end

#rowsObject

A Hash of :first_name => “<tr><td>First Name</td><td>Bob</td></tr>”



10
11
12
# File 'app/models/effective/table_builder.rb', line 10

def rows
  @rows
end

#templateObject

Returns the value of attribute template.



7
8
9
# File 'app/models/effective/table_builder.rb', line 7

def template
  @template
end

Instance Method Details

#article_editor(name, options = {}) ⇒ Object



123
124
125
# File 'app/models/effective/table_builder.rb', line 123

def article_editor(name, options = {})
  rows[name] = TableRows::ArticleEditor.new(name, options, builder: self).to_html
end

#belongs_to(name, options = {}) ⇒ Object



143
144
145
# File 'app/models/effective/table_builder.rb', line 143

def belongs_to(name, options = {})
  rows[name] = TableRows::BelongsTo.new(name, options, builder: self).to_html
end

#boolean_row(name, options = {}) ⇒ Object Also known as: check_box



127
128
129
# File 'app/models/effective/table_builder.rb', line 127

def boolean_row(name, options = {})
  rows[name] = TableRows::Boolean.new(name, options, builder: self).to_html
end

#build_resource_rows(only: nil, except: nil) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'app/models/effective/table_builder.rb', line 66

def build_resource_rows(only: nil, except: nil)
  Effective::Resource.new(object).resource_attributes.each do |name, options|
    next if only.present? && only.exclude?(name)
    next if except.present? && except.include?(name)

    case options.first
    when :active_storage
      file_field(name)
    when :belongs_to
      belongs_to(name)
    when :effective_address
      effective_address(name)
    when :boolean
      boolean_row(name)
    when :integer
      if ['price', 'discount', '_fee'].any? { |p| name.to_s.include?(p) }
        price_field(name)
      elsif ['_percent'].any? { |p| name.to_s.include?(p) }
        percent_field(name)
      else
        text_field(name)
      end
    when :string
      name.to_s.include?('email') ? email_field(name) : text_field(name)
    when :text
      text_area(name)
    else default_row(name)
    end
  end
end

#capture(&block) ⇒ Object



57
58
59
60
61
62
63
64
# File 'app/models/effective/table_builder.rb', line 57

def capture(&block)
  begin
    template.instance_variable_set(:@_effective_table_builder, self)
    template.capture(self, &block)
  ensure
    template.instance_variable_set(:@_effective_table_builder, nil)
  end
end

#collection_row(name, collection, options = {}, &block) ⇒ Object Also known as: select, checks, radios



132
133
134
135
136
137
138
# File 'app/models/effective/table_builder.rb', line 132

def collection_row(name, collection, options = {}, &block)
  rows[name] = if [true, false].include?(value(name))
    TableRows::Boolean.new(name, options, builder: self).to_html
  else
    TableRows::Collection.new(name, collection, options, builder: self).to_html
  end
end

#content_for(name, options = {}, &block) ⇒ Object



216
217
218
# File 'app/models/effective/table_builder.rb', line 216

def content_for(name, options = {}, &block)
  content_fors[name] = TableRows::ContentFor.new(name, options, builder: self).to_html(&block)
end

#date_field(name, options = {}) ⇒ Object



147
148
149
# File 'app/models/effective/table_builder.rb', line 147

def date_field(name, options = {})
  rows[name] = TableRows::DateField.new(name, options, builder: self).to_html
end

#datetime_field(name, options = {}) ⇒ Object



151
152
153
# File 'app/models/effective/table_builder.rb', line 151

def datetime_field(name, options = {})
  rows[name] = TableRows::DatetimeField.new(name, options, builder: self).to_html
end

#default_row(name, options = {}, &block) ⇒ Object

Assign the <tr><td>…</td></tr> to the @rows Hash



119
120
121
# File 'app/models/effective/table_builder.rb', line 119

def default_row(name, options = {}, &block)
  rows[name] = TableRow.new(name, options, builder: self).to_html
end

#effective_address(name, options = {}) ⇒ Object



180
181
182
# File 'app/models/effective/table_builder.rb', line 180

def effective_address(name, options = {})
  rows[name] = TableRows::EffectiveAddress.new(name, options, builder: self).to_html
end

#email_field(name, options = {}) ⇒ Object Also known as: email_cc_field



155
156
157
# File 'app/models/effective/table_builder.rb', line 155

def email_field(name, options = {})
  rows[name] = TableRows::EmailField.new(name, options, builder: self).to_html
end

#fields_for(name, object, options = {}, &block) ⇒ Object Also known as: effective_fields_for



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'app/models/effective/table_builder.rb', line 242

def fields_for(name, object, options = {}, &block)
  values = value(name)

  if values.respond_to?(:each_with_index)
    values.each_with_index do |object, index|
      builder = TableBuilder.new(object, template, options.reverse_merge(prefix: human_attribute_name(name).singularize + " ##{index+1}"))
      builder.render(&block)
      builder.rows.each { |child, content| rows["#{name}_#{child}_#{index}".to_sym] = content }
    end
  else
    builder = TableBuilder.new(object, template, options.merge(prefix: human_attribute_name(name)))
    builder.render(&block)
    builder.rows.each { |child, content| rows["#{name}_#{child}".to_sym] = content }
  end
end

#file_field(name, options = {}) ⇒ Object



160
161
162
# File 'app/models/effective/table_builder.rb', line 160

def file_field(name, options = {})
  rows[name] = TableRows::FileField.new(name, options, builder: self).to_html
end

#filter_parametersObject



97
98
99
# File 'app/models/effective/table_builder.rb', line 97

def filter_parameters
  FILTER_PARAMETERS + Array(object.class.try(:filter_parameters)) + Array(Rails.application.config.filter_parameters)
end

#form_group(name = nil, options = {}, &block) ⇒ Object



164
165
166
# File 'app/models/effective/table_builder.rb', line 164

def form_group(name = nil, options = {}, &block)
  # Nothing to do
end

#has_many(name, collection = nil, options = {}, &block) ⇒ Object

Has Many



234
235
236
237
238
239
240
# File 'app/models/effective/table_builder.rb', line 234

def has_many(name, collection = nil, options = {}, &block)
  value(name).each_with_index do |object, index|
    builder = TableBuilder.new(object, template, options.reverse_merge(prefix: human_attribute_name(name).singularize + " ##{index+1}"))
    builder.render(&block)
    builder.rows.each { |child, content| rows["#{name}_#{child}_#{index}".to_sym] = content }
  end
end

#hidden_field(name = nil, options = {}) ⇒ Object



168
169
170
# File 'app/models/effective/table_builder.rb', line 168

def hidden_field(name = nil, options = {})
  # Nothing to do
end

#hide_if(name, selected, &block) ⇒ Object

Logics



221
222
223
# File 'app/models/effective/table_builder.rb', line 221

def hide_if(name, selected, &block)
  template.capture(self, &block) unless value(name) == selected
end

#human_attribute_name(name) ⇒ Object



101
102
103
104
105
106
107
# File 'app/models/effective/table_builder.rb', line 101

def human_attribute_name(name)
  if object.respond_to?(:human_attribute_name)
    object.human_attribute_name(name)
  else
    (name.to_s.split('.').last.to_s.titleize || '')
  end
end

#password_field(name, options = {}) ⇒ Object



176
177
178
# File 'app/models/effective/table_builder.rb', line 176

def password_field(name, options = {})
  # Nothing to do
end

#percent_field(name, options = {}) ⇒ Object



184
185
186
# File 'app/models/effective/table_builder.rb', line 184

def percent_field(name, options = {})
  rows[name] = TableRows::PercentField.new(name, options, builder: self).to_html
end

#price_field(name, options = {}) ⇒ Object



192
193
194
# File 'app/models/effective/table_builder.rb', line 192

def price_field(name, options = {})
  rows[name] = TableRows::PriceField.new(name, options, builder: self).to_html
end

#render(&block) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'app/models/effective/table_builder.rb', line 26

def render(&block)
  # This runs the form partial over this table builder
  capture(&block) if block_given?

  # Consider content
  only = Array(options[:only])
  except = Array(options[:except])
  additionally = Array(options[:additionally])
  filtered = filter_parameters

  # Rows are created when we use the block syntax and call a f.text_field or other f.form_field
  # Using = f.content_for does not create a row.
  # So rows wille be blank when using the default syntax
  # And rows will be present when we render a form, or any form fields
  build_resource_rows(only: only, except: except) if rows.blank?

  # This gives us a second run through the rows, if you pass additionally
  build_resource_rows(only: additionally) if additionally.present?

  # Use f.content_for :name to override the content
  content = rows.merge(content_fors)

  # Filter out some hardcoded ones
  content = content.except(*filtered) if filtered.present?
  content = content.except(*except) if except.present?

  (:table, class: options.fetch(:class, 'table table-sm table-striped table-hover effective-table-summary')) do
    (:tbody, content.values.join.html_safe)
  end
end

#save(name = nil, options = {}) ⇒ Object



196
197
198
# File 'app/models/effective/table_builder.rb', line 196

def save(name = nil, options = {})
  # Nothing to do
end

#search_field(name, options = {}) ⇒ Object



172
173
174
# File 'app/models/effective/table_builder.rb', line 172

def search_field(name, options = {})
  # Nothing to do
end

#show_if(name, selected, &block) ⇒ Object



225
226
227
# File 'app/models/effective/table_builder.rb', line 225

def show_if(name, selected, &block)
  template.capture(self, &block) if value(name) == selected
end

#show_if_any(name, options, &block) ⇒ Object



229
230
231
# File 'app/models/effective/table_builder.rb', line 229

def show_if_any(name, options, &block)
  template.capture(self, &block) if Array(options).include?(value(name))
end

#static_field(name, options = {}, &block) ⇒ Object



204
205
206
# File 'app/models/effective/table_builder.rb', line 204

def static_field(name, options = {}, &block)
  rows[name] = (value(name).is_a?(ActiveRecord::Base)) ? belongs_to(name, options) : default_row(name, options)
end

#submit(name = nil, options = {}, &block) ⇒ Object



200
201
202
# File 'app/models/effective/table_builder.rb', line 200

def submit(name = nil, options = {}, &block)
  # Nothing to do
end

#tel_field(name, options = {}) ⇒ Object



188
189
190
# File 'app/models/effective/table_builder.rb', line 188

def tel_field(name, options = {})
  rows[name] = TableRows::PhoneField.new(name, options, builder: self).to_html
end

#text_area(name, options = {}) ⇒ Object



208
209
210
# File 'app/models/effective/table_builder.rb', line 208

def text_area(name, options = {})
  rows[name] = TableRows::TextArea.new(name, options, builder: self).to_html
end

#url_field(name, options = {}) ⇒ Object



212
213
214
# File 'app/models/effective/table_builder.rb', line 212

def url_field(name, options = {})
  rows[name] = TableRows::UrlField.new(name, options, builder: self).to_html
end

#value(name) ⇒ Object



109
110
111
# File 'app/models/effective/table_builder.rb', line 109

def value(name)
  object.send(name)
end