Class: Ruflet::Rails::ResourceComponent

Inherits:
Object
  • Object
show all
Includes:
UI::SharedControlForwarders
Defined in:
lib/ruflet/rails/resource_component.rb

Overview

Base class for a Ruflet CRUD resource.

The generated subclass owns the explicit CRUD UI (render, show, the create/edit form) AND the database calls (record.update, record.destroy!, model_class.new) — so a developer can read and change anything. This base provides only reusable, non-DB helpers: model resolution, record loading, field inference (resource_fields/display_fields/display_value), navigation (render_index/render_show/refresh), dialog management, snackbars, and the date/time picker value helpers.

The same subclass renders on web and on mobile/desktop. It is mounted from config/routes.rb (the route path is declared there, never in the component):

mount Ruflet::Rails.web_app(view: "ProductComponent"), at: "/products"

web_app(view:) calls ‘.render(page)` on the class, which is why the class method below is the entrypoint. The model is inferred from the class name (ProductComponent -> Product); override `model_class` to customize.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(page, controller: nil) ⇒ ResourceComponent

Returns a new instance of ResourceComponent.



72
73
74
75
# File 'lib/ruflet/rails/resource_component.rb', line 72

def initialize(page, controller: nil)
  @page = page
  @controller = controller
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, **kwargs, &block) ⇒ Object (private)

Methods not found on the component fall back to an optional controller, kept for apps that still pair a component with a separate host object.



360
361
362
363
364
# File 'lib/ruflet/rails/resource_component.rb', line 360

def method_missing(name, *args, **kwargs, &block)
  return controller.__send__(name, *args, **kwargs, &block) if controller&.respond_to?(name, true)

  super
end

Instance Attribute Details

#controllerObject (readonly)

Returns the value of attribute controller.



32
33
34
# File 'lib/ruflet/rails/resource_component.rb', line 32

def controller
  @controller
end

#pageObject (readonly)

Returns the value of attribute page.



32
33
34
# File 'lib/ruflet/rails/resource_component.rb', line 32

def page
  @page
end

Class Method Details

.model(value = nil) ⇒ Object

Declare or read the managed model: ‘model Product` or inferred from the component class name.



42
43
44
45
# File 'lib/ruflet/rails/resource_component.rb', line 42

def model(value = nil)
  @model_class = value if value
  @model_class || inferred_model_class
end

.render(page, *_args) ⇒ Object

Entrypoint used by web_app(view: “…”) on each new session.



36
37
38
# File 'lib/ruflet/rails/resource_component.rb', line 36

def render(page, *_args)
  new(page).render_index
end

.singular_titleObject



53
54
55
# File 'lib/ruflet/rails/resource_component.rb', line 53

def singular_title
  model_name ? model_name.human.titleize : "Record"
end

.title(value = nil) ⇒ Object

Declare or read the plural resource title shown on the index screen.



48
49
50
51
# File 'lib/ruflet/rails/resource_component.rb', line 48

def title(value = nil)
  @resource_title = value if value
  @resource_title || (model_name ? model_name.plural.humanize.titleize : "Resources")
end

Instance Method Details

#display_fieldsObject

Columns rendered in the index table / list tiles.



99
100
101
# File 'lib/ruflet/rails/resource_component.rb', line 99

def display_fields
  resource_fields
end

#display_value(record, field) ⇒ Object

Formats a single field for display. Override for custom rendering.



104
105
106
# File 'lib/ruflet/rails/resource_component.rb', line 104

def display_value(record, field)
  record.public_send(field).to_s
end

#model_classObject

— Resource configuration (override in the generated subclass) ——–



79
80
81
# File 'lib/ruflet/rails/resource_component.rb', line 79

def model_class
  self.class.model
end

#primary_label(record) ⇒ Object

— Index labels ——————————————————-



139
140
141
142
# File 'lib/ruflet/rails/resource_component.rb', line 139

def primary_label(record)
  field = display_fields.first
  field ? display_value(record, field) : "##{record_id(record)}"
end

#recordsObject

— Record loading & persistence ————————————–



110
111
112
113
# File 'lib/ruflet/rails/resource_component.rb', line 110

def records
  scope = model_class.respond_to?(:limit) ? model_class.limit(50) : model_class.all
  scope.respond_to?(:limit) ? scope.limit(50) : scope.to_a.first(50)
end

#refreshObject

Re-render the index after a create/update/destroy. The generated component calls this from its own (explicit) save/destroy code.



133
134
135
# File 'lib/ruflet/rails/resource_component.rb', line 133

def refresh
  render_index
end

#render_indexObject



115
116
117
118
119
# File 'lib/ruflet/rails/resource_component.rb', line 115

def render_index
  page.title = resource_title
  page.views = []
  page.add(render)
end

#render_show(record) ⇒ Object



121
122
123
124
125
# File 'lib/ruflet/rails/resource_component.rb', line 121

def render_show(record)
  page.views = []
  page.add(show(record))
  page.update
end

#resource_fieldsObject

Fields rendered on the detail (show) screen. The generated subclass overrides this with the scaffolded attributes; the default falls back to the model’s own attribute names.



94
95
96
# File 'lib/ruflet/rails/resource_component.rb', line 94

def resource_fields
  default_resource_fields
end

#resource_titleObject



83
84
85
# File 'lib/ruflet/rails/resource_component.rb', line 83

def resource_title
  self.class.title
end

#secondary_label(record) ⇒ Object



144
145
146
147
# File 'lib/ruflet/rails/resource_component.rb', line 144

def secondary_label(record)
  field = display_fields[1]
  field ? display_value(record, field) : nil
end

#show_record(record) ⇒ Object



127
128
129
# File 'lib/ruflet/rails/resource_component.rb', line 127

def show_record(record)
  render_show(record)
end

#singular_titleObject



87
88
89
# File 'lib/ruflet/rails/resource_component.rb', line 87

def singular_title
  model_class.respond_to?(:model_name) ? model_class.model_name.human.titleize : self.class.singular_title
end