Module: Brick::Rails::FormBuilder
- Defined in:
- lib/brick/frameworks/rails/form_builder.rb
Constant Summary collapse
- DT_PICKERS =
{ datetime: 'datetimepicker', timestamp: 'datetimepicker', time: 'timepicker', date: 'datepicker' }
Instance Method Summary collapse
-
#brick_field(method, html_options = {}, val = nil, col = nil, bt = nil, bt_class = nil, bt_name = nil, bt_pair = nil) ⇒ Object
Render an editable field When it’s one of these types, will set an appropriate instance variable truthy accordingly: @_text_fields_present - To include trix editor @_date_fields_present - To include flatpickr date / time editor @_json_fields_present - To include JSONEditor.
Instance Method Details
#brick_field(method, html_options = {}, val = nil, col = nil, bt = nil, bt_class = nil, bt_name = nil, bt_pair = nil) ⇒ Object
Render an editable field When it’s one of these types, will set an appropriate instance variable truthy accordingly:
@_text_fields_present - To include trix editor
@_date_fields_present - To include flatpickr date / time editor
@_json_fields_present - To include JSONEditor
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 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 56 57 58 59 60 61 62 63 64 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 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/brick/frameworks/rails/form_builder.rb', line 9 def brick_field(method, = {}, val = nil, col = nil, bt = nil, bt_class = nil, bt_name = nil, bt_pair = nil) model = self.object.class col ||= model.columns_hash[method] out = +'<table><tr><td>' [:class] = 'dimmed' unless val is_revert = true template = instance_variable_get(:@template) if bt bt_class ||= bt[1].first.first bt_name ||= bt[1].map { |x| x.first.name }.join('/') bt_pair ||= bt[1].first [:prompt] = "Select #{bt_name}" out << self.select(method.to_sym, bt[3], { value: val || '^^^brick_NULL^^^' }, ) bt_obj = nil begin bt_obj = bt_class&.find_by(bt_pair[1] => val) rescue ActiveRecord::SubclassNotFound => e # %%% Would be cool to indicate to the user that a subclass is missing. # Its name starts at: e.message.index('failed to locate the subclass: ') + 31 end bt_link = if bt_obj bt_path = template.send( "#{bt_class.base_class._brick_index(:singular)}_path".to_sym, bt_obj.send(bt_class.primary_key.to_sym) ) template.link_to('⇛', bt_path, { class: 'show-arrow' }) elsif val "<span class=\"orphan\">Orphaned ID: #{val}</span>".html_safe end out << bt_link if bt_link elsif model._brick_monetized_attributes&.include?(method) out << self.text_field(method.to_sym, .merge({ value: Money.new(val.to_i).format })) else col_type = if model.json_column?(col) || val.is_a?(Array) :json elsif col&.sql_type == 'geography' col.sql_type else col&.type end case (col_type ||= col&.sql_type) when :string, :text, :citext, :enum # Support for the activerecord-mysql-enum gem spit_out_text_field = nil if ::Brick::Rails.is_bcrypt?(val) # || .readonly? is_revert = false out << ::Brick::Rails.hide_bcrypt(val, nil, 1000) elsif col_type == :string if model.respond_to?(:uploaders) && model.uploaders.key?(col.name&.to_sym) && (url = self.object.send(col.name)&.url) # Carrierwave image? out << "<img src=\"#{url}\" title=\"#{val}\">" elsif model.respond_to?(:enumerized_attributes) && (opts = (attr = model.enumerized_attributes[method])&.).present? = attr.kind_of?(Enumerize::Multiple) ? .merge({ multiple: true, size: opts.length + 1 }) : out << self.select(method.to_sym, [["(No #{method} chosen)", '^^^brick_NULL^^^']] + opts, { value: val || '^^^brick_NULL^^^' }, ) else spit_out_text_field = true end elsif col_type == :enum if col.respond_to?(:limit) && col.limit.present? out << self.select(method.to_sym, [["(No #{method} chosen)", '^^^brick_NULL^^^']] + col.limit, { value: val.to_s || '^^^brick_NULL^^^' }, ) else spit_out_text_field = true end else template.instance_variable_set(:@_text_fields_present, true) out << self.hidden_field(method.to_sym, ) out << "<trix-editor input=\"#{self.field_id(method)}\"></trix-editor>" end out << self.text_field(method.to_sym, ) if spit_out_text_field when :boolean out << self.check_box(method.to_sym) when :integer, :decimal, :float if model.respond_to?(:attribute_types) && (enum_type = model.attribute_types[method]).is_a?(ActiveRecord::Enum::EnumType) opts = enum_type.send(:mapping)&.each_with_object([]) { |v, s| s << [v.first, v.first] } || [] out << self.select(method.to_sym, [["(No #{method} chosen)", '^^^brick_NULL^^^']] + opts, { value: val || '^^^brick_NULL^^^' }, ) else digit_pattern = col_type == :integer ? '(?:-|)\d*' : '(?:-|)\d*(?:\.\d*|)' # Used to do this for float / decimal: self.number_field method.to_sym out << self.text_field(method.to_sym, { pattern: digit_pattern, class: 'check-validity' }) end when *DT_PICKERS.keys template.instance_variable_set(:@_date_fields_present, true) out << self.text_field(method.to_sym, { class: DT_PICKERS[col_type] }) when :uuid is_revert = false # Postgres naturally uses the +uuid_generate_v4()+ function from the uuid-ossp extension # If it's not yet enabled then: create extension \"uuid-ossp\"; # ActiveUUID gem created a new :uuid type out << val if val when :ltree # In Postgres labels of data stored in a hierarchical tree-like structure # If it's not yet enabled then: create extension ltree; out << val if val when :binary is_revert = false if val out << if ::Brick.is_geography?(val) ::Brick::Rails.display_value('geography', val) else ::Brick::Rails.display_binary(val) end end when :file, :files if attached = begin self.object.send(method) rescue end # Show any existing image(s) existing = [] got_one = nil (attached.respond_to?(:attachments) ? attached. : [attached]).each do || next unless (blob = .blob) existing << blob.key out << "#{blob.filename}<br>" url = begin self.object.send(method)&.url rescue StandardError => e # Another possible option: # Rails.application.routes.url_helpers.rails_blob_path(attachment, only_path: true) Rails.application.routes.url_helpers.rails_storage_proxy_path(, only_path: true) end out << if url "<img src=\"#{url}\" title=\"#{val}\">" else # Convert the raw binary to a Base64 image ::Brick::Rails.display_binary(.download, 500_000) end got_one = true out << '<br>' end out << 'Update: ' if got_one end out << self.hidden_field("_brick_attached_#{method}", value: existing.join(',')) unless existing.blank? # Render a "Choose File(s)" input element args = [method.to_sym] args << { multiple: true } if col&.type == :files out << self.file_field(*args) when :primary_key is_revert = false when :json, :jsonb template.instance_variable_set(:@_json_fields_present, true) if val.is_a?(String) val_str = val else eheij = ActiveSupport::JSON::Encoding.escape_html_entities_in_json ActiveSupport::JSON::Encoding.escape_html_entities_in_json = false if eheij val_str = val&.to_json ActiveSupport::JSON::Encoding.escape_html_entities_in_json = eheij end # Because there are so danged many quotes in JSON, escape them specially by converting to backticks. # (and previous to this, escape backticks with our own goofy code of ^^br_btick__ ) out << (json_field = self.hidden_field(method.to_sym, { class: 'jsonpicker', value: val_str&.gsub('`', '^^br_btick__')&.tr('\"', '`')&.html_safe })) out << "<div id=\"_br_json_#{self.field_id(method)}\"></div>" else is_revert = false out << (::Brick::Rails.display_value(col_type, val)&.html_safe || '') end end if is_revert out << "</td> " out << '<td><svg class="revert" width="1.5em" viewBox="0 0 512 512"><use xlink:href="#revertPath" /></svg>' end out << "</td></tr></table> " out.html_safe end |