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



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

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



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

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

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



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

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



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

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



65
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
# File 'app/models/effective/table_builder.rb', line 65

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



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

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



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

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



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

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



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

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

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



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

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



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

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

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



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

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



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

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



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

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



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

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

#filter_parametersObject



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

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



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

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

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

Has Many



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

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



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

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

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

Logics



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

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

#human_attribute_name(name) ⇒ Object



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

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



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

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

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



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

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

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



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

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
# 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?

  (: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



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

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

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



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

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

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



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

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

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



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

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

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



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

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



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

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

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



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

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

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



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

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

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



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

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

#value(name) ⇒ Object



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

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