Class: Madmin::Resource

Inherits:
Object
  • Object
show all
Defined in:
lib/madmin/resource.rb

Class Method Summary collapse

Class Method Details

.attribute(name, type = nil, **options) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/madmin/resource.rb', line 37

def attribute(name, type = nil, **options)
  type ||= infer_type(name)
  field = options[:field] || field_for_type(type)

  attributes[name] = OpenStruct.new(
    name: name,
    type: type,
    field: field.new(**options.merge(attribute_name: name, model: model, resource: self))
  )
rescue => e
  builder = ResourceBuilder.new(model)
  raise ArgumentError, "    Madmin couldn't find attribute or association '\#{name}' on \#{model} model.\n\n    We searched these attributes and associations:\n    \#{(builder.attributes + builder.associations).join(\", \")}\n\n    This attribute is defined in a Madmin resource at:\n    \#{e.backtrace.find { |l| l =~ /_resource.rb/ }}\n\n    Either add the missing attribute or assocation, or remove this line from your Madmin resource.\n  MESSAGE\nend\n"

.display_name(record) ⇒ Object



99
100
101
# File 'lib/madmin/resource.rb', line 99

def display_name(record)
  "#{record.class} ##{record.id}"
end

.edit_path(record) ⇒ Object



87
88
89
# File 'lib/madmin/resource.rb', line 87

def edit_path(record)
  url_helpers.polymorphic_path([:madmin, route_namespace, record], action: :edit)
end

.field_for_type(type) ⇒ Object



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
178
179
180
# File 'lib/madmin/resource.rb', line 119

def field_for_type(type)
  {
    binary: Fields::String,
    blob: Fields::Text,
    boolean: Fields::Boolean,
    date: Fields::Date,
    datetime: Fields::DateTime,
    decimal: Fields::Decimal,
    enum: Fields::Enum,
    float: Fields::Float,
    hstore: Fields::Json,
    integer: Fields::Integer,
    json: Fields::Json,
    jsonb: Fields::Json,
    primary_key: Fields::String,
    string: Fields::String,
    text: Fields::Text,
    time: Fields::Time,
    timestamp: Fields::Time,
    timestamptz: Fields::Time,
    password: Fields::Password,
    file: Fields::File,

    # Postgres specific types
    bit: Fields::String,
    bit_varying: Fields::String,
    box: Fields::String,
    cidr: Fields::String,
    circle: Fields::String,
    citext: Fields::Text,
    daterange: Fields::String,
    inet: Fields::String,
    int4range: Fields::String,
    int8range: Fields::String,
    interval: Fields::String,
    line: Fields::String,
    lseg: Fields::String,
    ltree: Fields::String,
    macaddr: Fields::String,
    money: Fields::String,
    numrange: Fields::String,
    oid: Fields::String,
    path: Fields::String,
    point: Fields::String,
    polygon: Fields::String,
    tsrange: Fields::String,
    tstzrange: Fields::String,
    tsvector: Fields::String,
    uuid: Fields::String,
    xml: Fields::Text,

    # Associations
    attachment: Fields::Attachment,
    attachments: Fields::Attachments,
    belongs_to: Fields::BelongsTo,
    polymorphic: Fields::Polymorphic,
    has_many: Fields::HasMany,
    has_one: Fields::HasOne,
    rich_text: Fields::RichText,
    nested_has_many: Fields::NestedHasMany
  }.fetch(type)
end

.friendly_model?Boolean



103
104
105
# File 'lib/madmin/resource.rb', line 103

def friendly_model?
  model.respond_to? :friendly
end

.friendly_nameObject



61
62
63
# File 'lib/madmin/resource.rb', line 61

def friendly_name
  model_name.gsub("::", " / ").split(/(?=[A-Z])/).join(" ")
end

.get_attribute(name) ⇒ Object



33
34
35
# File 'lib/madmin/resource.rb', line 33

def get_attribute(name)
  attributes[name]
end

.index_path(options = {}) ⇒ Object



75
76
77
# File 'lib/madmin/resource.rb', line 75

def index_path(options = {})
  url_helpers.polymorphic_path([:madmin, route_namespace, model], options)
end

.infer_type(name) ⇒ Object



182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/madmin/resource.rb', line 182

def infer_type(name)
  name_string = name.to_s

  if model.attribute_types.include?(name_string)
    column_type = model.attribute_types[name_string]
    if column_type.is_a? ::ActiveRecord::Enum::EnumType
      :enum
    else
      column_type.type || :string
    end
  elsif (association = model.reflect_on_association(name))
    type_for_association(association)
  elsif model.reflect_on_association(:"rich_text_#{name_string}")
    :rich_text
  elsif model.reflect_on_association(:"#{name_string}_attachment")
    :attachment
  elsif model.reflect_on_association(:"#{name_string}_attachments")
    :attachments

  # has_secure_password
  elsif model.attribute_types.include?("#{name_string}_digest") || name_string.ends_with?("_confirmation")
    :password

    # ActiveRecord Store
  elsif model_store_accessors.include?(name)
    :string
  end
end

.inherited(base) ⇒ Object



10
11
12
13
14
15
# File 'lib/madmin/resource.rb', line 10

def inherited(base)
  base.attributes = attributes.dup
  base.member_actions = scopes.dup
  base.scopes = scopes.dup
  super
end

.member_action(&block) ⇒ Object



115
116
117
# File 'lib/madmin/resource.rb', line 115

def member_action(&block)
  member_actions << block
end

.modelObject



17
18
19
# File 'lib/madmin/resource.rb', line 17

def model
  @model ||= model_name.constantize
end

.model_find(id) ⇒ Object



21
22
23
# File 'lib/madmin/resource.rb', line 21

def model_find(id)
  friendly_model? ? model.friendly.find(id) : model.find(id)
end

.model_nameObject



25
26
27
# File 'lib/madmin/resource.rb', line 25

def model_name
  to_s.chomp("Resource").classify
end

.model_store_accessorsObject



227
228
229
230
# File 'lib/madmin/resource.rb', line 227

def model_store_accessors
  store_accessors = model.stored_attributes.values
  store_accessors.flatten
end

.new_pathObject



79
80
81
# File 'lib/madmin/resource.rb', line 79

def new_path
  url_helpers.polymorphic_path([:madmin, route_namespace, model], action: :new)
end

.param_keyObject



91
92
93
# File 'lib/madmin/resource.rb', line 91

def param_key
  model.model_name.param_key
end

.permitted_paramsObject



95
96
97
# File 'lib/madmin/resource.rb', line 95

def permitted_params
  attributes.values.filter { |a| a.field.visible?(:form) }.map { |a| a.field.to_param }
end

.route_namespaceObject

Support for isolated namespaces Finds parent module class to include in polymorphic urls



67
68
69
70
71
72
73
# File 'lib/madmin/resource.rb', line 67

def route_namespace
  return @route_namespace if instance_variable_defined?(:@route_namespace)
  namespace = model.module_parents.detect do |n|
    n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
  end
  @route_namespace = (namespace ? namespace.name.singularize.underscore.to_sym : nil)
end

.scope(name) ⇒ Object



29
30
31
# File 'lib/madmin/resource.rb', line 29

def scope(name)
  scopes << name
end

.searchable_attributesObject



111
112
113
# File 'lib/madmin/resource.rb', line 111

def searchable_attributes
  attributes.values.select { |a| a.field.searchable? }
end

.show_path(record) ⇒ Object



83
84
85
# File 'lib/madmin/resource.rb', line 83

def show_path(record)
  url_helpers.polymorphic_path([:madmin, route_namespace, record])
end

.sortable_columnsObject



107
108
109
# File 'lib/madmin/resource.rb', line 107

def sortable_columns
  model.column_names
end

.type_for_association(association) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
# File 'lib/madmin/resource.rb', line 211

def type_for_association(association)
  if association.has_one?
    :has_one
  elsif association.collection?
    :has_many
  elsif association.polymorphic?
    :polymorphic
  else
    :belongs_to
  end
end

.url_helpersObject



223
224
225
# File 'lib/madmin/resource.rb', line 223

def url_helpers
  @url_helpers ||= Rails.application.routes.url_helpers
end