Module: Pxs::Forms::ModelsHelper

Includes:
ActionView::Context, LinksHelper
Included in:
ModelFormBuilder
Defined in:
lib/pxs/forms/models_helper.rb

Instance Method Summary collapse

Methods included from LinksHelper

#link_button_to, #turbo_link_button, #turbo_link_to

Instance Method Details

#input_name_to_id(name) ⇒ Object

to convert something like “project” to “project-client”



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
# File 'lib/pxs/forms/models_helper.rb', line 136

def input_name_to_id(name)
    match = match_model_input_name name

    # return nil on bad input
    return nil unless match

    # create a working copy because will be modified later
    working_name = name

    # first capture group is the starting point of the ID, to kebabcase
    id = match[1].kebabcase

    loop do
        if match[2]

            # only match with character strings, ignore indexes for now
            #! might lead to some issues if ever there comes a point where this is used in one-to-many relationships with multiple models displayed on the same page
            if association = match[2].match(/\[([A-Za-z_]+)\]/)
                id << "-#{association[1].kebabcase}"
            end
        end

        # break after the first check, so the first set of bracket is processed coming into the loop
        break unless match[2]

        # remove the first set of [] from the name string, intending to repeat the process over and over until each has been removed
        working_name.gsub!(match[2], "")

        # match again
        match = match_model_input_name working_name
    end

    # id should contain the base model and associated models in a kebabcase string, like "project-client-contacts-first-name"
    id
end

#input_name_to_select_id(name) ⇒ Object



172
173
174
175
176
177
178
179
180
181
# File 'lib/pxs/forms/models_helper.rb', line 172

def input_name_to_select_id(name)
    match = match_model_input_name name

    return nil unless match[3]

    object_name = match[1]
    association_name = match[3].chomp("_attributes")

    "#{object_name}_#{association_name}"
end

#model_association_form(form_name = "") ⇒ Object

form_name => a string that matches the input elements HTML name attribute, like “project[contacts][coordinate]”



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/pxs/forms/models_helper.rb', line 117

def model_association_form(form_name = "")

    # isolate the original model class from the submodels
    form_model, *nested_attributes = form_name.split(/\[|\]/).compact_blank

    # simulate the top-level form using a new instance of form_model
    fields form_model.classify.constantize.new do |form|
        form.set_association_prefixes(form_name)

        # recursively build the subforms, going as deep as needed to reach the association model form
        nested_form_builder_for form, nested_attributes do |nested_form|

            # run once for the last iteration (the association model)
            return nested_form
        end
    end
end

#model_button_id(model, button_action = nil) ⇒ Object

shorthand to set model form button IDs for instance, model_button_id(client, :new) == ‘new-client-button’



71
72
73
# File 'lib/pxs/forms/models_helper.rb', line 71

def model_button_id(model, button_action = nil)
    model_html_id "#{button_action.present? ? "#{button_action.to_s.kebabcase}-" : ""}#{model_string(model).kebabcase}", :button
end

#model_cancel_form_button(base_path, label = nil) ⇒ Object

“Cancel” new model button



34
35
36
# File 'lib/pxs/forms/models_helper.rb', line 34

def model_cancel_form_button(base_path, label = nil)
    turbo_link_button(label || t('keywords.cancel'), "#{base_path}?cancel=true")
end

#model_delete_action(base_path, label = nil) ⇒ Object

“Delete” model button



24
25
26
# File 'lib/pxs/forms/models_helper.rb', line 24

def model_delete_action(base_path, label = nil)
    turbo_link_button(label || t('keywords.delete'), base_path, method: :delete )
end

#model_edit_action(base_path, label = nil) ⇒ Object

“Edit” model button



18
19
20
21
# File 'lib/pxs/forms/models_helper.rb', line 18

def model_edit_action(base_path, label = nil)
    #! maybe there's a safer way to do the route but this works as long as rails routing naming conventions hold
    turbo_link_button(label || t('keywords.edit'), "#{base_path}/edit")
end

#model_edit_delete_actions(base_path, options = {}) ⇒ Object

base_path: the model’s CRUD base path as an URL string, like the result of article_path(:id)



8
9
10
11
12
13
14
15
# File 'lib/pxs/forms/models_helper.rb', line 8

def model_edit_delete_actions(base_path, options = {})
    [
        # edit model button
        model_edit_action(base_path, options[:edit_label]),
        # delete model button
        model_delete_action(base_path, options[:delete_label])
    ].join('').html_safe
end

#model_form_for(name, *args, &block) ⇒ Object

standardized form call for models (using form_for)



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/pxs/forms/models_helper.rb', line 76

def model_form_for(name, *args, &block)
    # set ModelFormBuilder as the form builder
    #! can be avoided by setting ModelFormBuilder as default in config
    options = args.extract_options!.merge(builder: ModelFormBuilder)

    #! use merge_option
    if options.has_key? :class
        options[:class] << " form"
    else
        options[:class] = "form"
    end

    # separate HTML options due to form_for parameter strucutre
    options[:html] = (options[:html] || {}).merge({ "class" => options[:class] })

    args << options

    form_for(name, *args, &block)
end

#model_form_id(model) ⇒ Object

Model subform <form> HTML ID



58
59
60
61
62
63
64
65
66
67
# File 'lib/pxs/forms/models_helper.rb', line 58

def model_form_id(model)
    # use the model class, not the model itself
    if model.is_a? ActiveRecord::Base
        model_class = model
    else
        model_class = model.class
    end

    model_html_id model_class.model_name.singular.kebabcase, :form
end

#model_form_with(model, scope: nil, url: nil, format: nil, **options, &block) ⇒ Object

standardized form call for models (using form_with)



97
98
99
100
101
102
103
# File 'lib/pxs/forms/models_helper.rb', line 97

def model_form_with(model, scope: nil, url: nil, format: nil, **options, &block)
    # set custom form builder (!should be done in config)
    options = options.reverse_merge(builder: ModelFormBuilder)

    # make the call
    form_with(model: model, scope: scope, url: url, format: format, class: "form#{(options.has_key? :class) ? " #{options[:class]}" : ""}", **options, &block)
end

#model_html_id(model, suffix = "") ⇒ Object

Model element HTML tag ID



46
47
48
49
# File 'lib/pxs/forms/models_helper.rb', line 46

def model_html_id(model, suffix = "")
    # model-suffix, or only model if no suffix is provided
    "#{model_string(model).kebabcase}#{suffix.present? ? "-#{suffix.to_s.kebabcase}" : ""}"
end

#model_new_action(base_path, label = nil) ⇒ Object

“New” model button



29
30
31
# File 'lib/pxs/forms/models_helper.rb', line 29

def model_new_action(base_path, label = nil)
    turbo_link_button(label || t('keywords.new'), "#{base_path}/new")
end

#model_string(model) ⇒ Object

!? what does this do again?



106
107
108
109
110
111
112
113
114
# File 'lib/pxs/forms/models_helper.rb', line 106

def model_string model
    if model.is_a? String
        model
    elsif model.is_a? ActiveRecord::Base || model.respond_to?(model_name)
        model.model_name.singular
    else
        model.to_s
    end
end

#model_submit_button(form, label = nil) ⇒ Object

“Create”/“Update” model model



39
40
41
42
43
# File 'lib/pxs/forms/models_helper.rb', line 39

def model_submit_button(form, label = nil)
    # adjust the label depending on whether the form's object has already been created or not
    label = label || "#{(form.object.new_record? ? t("keywords.create") : t("keywords.update"))} #{form.object.class.to_s}"
    form.submit label
end

#model_title_id(model) ⇒ Object

Model subform title HTML ID



52
53
54
55
# File 'lib/pxs/forms/models_helper.rb', line 52

def model_title_id(model)
    # some-model-title
    model_html_id model.class.model_name.singular.kebabcase, :title
end