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



111
112
113
# File 'app/models/effective/table_builder.rb', line 111

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



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

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

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



140
141
142
# File 'app/models/effective/table_builder.rb', line 140

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



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

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



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

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



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

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



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

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

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



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

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



116
117
118
# File 'app/models/effective/table_builder.rb', line 116

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

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



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

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



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

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



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

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



157
158
159
# File 'app/models/effective/table_builder.rb', line 157

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

#filter_parametersObject



94
95
96
# File 'app/models/effective/table_builder.rb', line 94

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



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

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

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

Has Many



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

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



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

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

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

Logics



218
219
220
# File 'app/models/effective/table_builder.rb', line 218

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

#human_attribute_name(name) ⇒ Object



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

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



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

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

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



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

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

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



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

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



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

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

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



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

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

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



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

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

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



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

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

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



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

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



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

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

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



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

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

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



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

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

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



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

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

#value(name) ⇒ Object



106
107
108
# File 'app/models/effective/table_builder.rb', line 106

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