Module: CafeCar::Helpers

Defined in:
lib/cafe_car/helpers.rb

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name) ⇒ Object



173
174
175
176
# File 'lib/cafe_car/helpers.rb', line 173

def method_missing(name, ...)
  return ui.send(name, ...) if name =~ /^[A-Z]/
  super
end

Instance Method Details

#ancestor_href?Boolean

Returns:

  • (Boolean)


67
# File 'lib/cafe_car/helpers.rb', line 67

def ancestor_href?(...) = URI(href_for(...)) < URI(url_for(request.url))

#body_classesObject



34
# File 'lib/cafe_car/helpers.rb', line 34

def body_classes = [ *controller_path.split(?/), action_name, *@body_class ]


122
123
124
# File 'lib/cafe_car/helpers.rb', line 122

def breadcrumbs(*items)
  ui.Row safe_join(items.compact_blank, icon(:nav_arrow_right, :dim))
end

#capObject



50
51
52
# File 'lib/cafe_car/helpers.rb', line 50

def cap(*)
  capture { cat(*) }
end

#captureObject



54
55
56
57
58
# File 'lib/cafe_car/helpers.rb', line 54

def capture(*, &)
  super do
    yield(*).then { _1.try(:html_safe?) ? _1.to_s : _1 }
  end
end

#cat(*args) ⇒ Object



42
43
44
45
46
47
48
# File 'lib/cafe_car/helpers.rb', line 42

def cat(*args)
  args.flatten.each do |arg|
    arg = capture(&arg) if arg.respond_to?(:to_proc)
    arg = arg.to_s
    concat(arg) if arg.present?
  end
end

#comment(text) ⇒ Object



145
146
147
# File 'lib/cafe_car/helpers.rb', line 145

def comment(text)
  "<!-- #{text} -->".html_safe
end

#console?Boolean

Returns:

  • (Boolean)


143
# File 'lib/cafe_car/helpers.rb', line 143

def console? = params.key?(:console)

#context(name = nil) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/cafe_car/helpers.rb', line 80

def context(name = nil, &)
  @context ||= []

  if block_given?
    @context << name
    r = capture(&)
    @context.pop
    r
  else
    @context
  end
end

#context?(*names) ⇒ Boolean

Returns:

  • (Boolean)


93
94
95
96
97
98
99
# File 'lib/cafe_car/helpers.rb', line 93

def context?(*names)
  context.reverse_each do |ctx|
    return true if names.empty?
    names.pop if ctx == names.last
  end
  names.empty?
end

#current_href?(check_parameters: false) ⇒ Boolean

Returns:

  • (Boolean)


66
# File 'lib/cafe_car/helpers.rb', line 66

def current_href?(*, check_parameters: false, **) = current_page?(href_for(*, **), check_parameters:)

#debug?Boolean

Returns:

  • (Boolean)


142
# File 'lib/cafe_car/helpers.rb', line 142

def debug?   = params.key?(:debug)

#filter_form_for(objects, **options, &block) ⇒ Object

Raises:

  • (ArgumentError)


126
127
128
129
130
131
132
133
134
135
136
# File 'lib/cafe_car/helpers.rb', line 126

def filter_form_for(objects, **options, &block)
  raise ArgumentError, "First argument to filter_form_for cannot be nil" if objects.nil?

  form_for CafeCar[:FilterBuilder].new(objects, parsed_params),
           builder: CafeCar["Filter::FormBuilder"],
           method: :get,
           url: "",
           as: "",
           **options,
           &block
end

#get_partial(path) ⇒ Object



154
155
156
157
# File 'lib/cafe_car/helpers.rb', line 154

def get_partial(path)
  prefixes = path.include?(?/) ? [] : lookup_context.prefixes
  lookup_context.find(path, prefixes, true)
end

#href_for(*parts, namespace: self.namespace, **params) ⇒ Object



69
70
71
# File 'lib/cafe_car/helpers.rb', line 69

def href_for(*parts, namespace: self.namespace, **params)
  HrefBuilder.new(*parts, namespace:, template: self, **params).to_s
end

#icon(name = nil) ⇒ Object



111
112
113
114
115
116
117
118
119
120
# File 'lib/cafe_car/helpers.rb', line 111

def icon(name = nil, *, **, &)
  case name
  when Symbol
    class_ = name&.then { "iconoir-#{_1.to_s.dasherize}" }
  when String, Array
    label = name
  end

  ui.Icon(*label, *, tag: :i, class: class_, **, &)
end


101
102
103
104
# File 'lib/cafe_car/helpers.rb', line 101

def link(object)
  @links         ||= {}
  @links[object] ||= CafeCar[:LinkBuilder].new(self, object)
end

Raises:

  • (ArgumentError)


106
107
108
109
# File 'lib/cafe_car/helpers.rb', line 106

def link_to(...)
  raise ArgumentError, "Links cannot be nested" if context?(:a)
  context(:a) { super }
end

#namespaceObject



169
170
171
# File 'lib/cafe_car/helpers.rb', line 169

def namespace
  @namespace ||= controller_path.split("/").tap(&:pop).map(&:to_sym)
end


165
166
167
# File 'lib/cafe_car/helpers.rb', line 165

def navigation
  @navigation ||= CafeCar::Navigation.new(self)
end

#partial?(path) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
152
# File 'lib/cafe_car/helpers.rb', line 149

def partial?(path)
  prefixes = path.include?(?/) ? [] : lookup_context.prefixes
  lookup_context.any?(path, prefixes, true)
end

#present(*args, **options) ⇒ Object Also known as: p



60
61
62
63
# File 'lib/cafe_car/helpers.rb', line 60

def present(*args, **options)
  @presenters                  ||= {}
  @presenters[[ args, options ]] ||= CafeCar[:Presenter].present(self, *args, **options)
end

#table_for(objects, **options, &block) ⇒ Object



138
139
140
# File 'lib/cafe_car/helpers.rb', line 138

def table_for(objects, **options, &block)
  CafeCar[:TableBuilder].new(self, objects:, **options, &block)
end

#template_glob(glob) ⇒ Object



159
160
161
162
163
# File 'lib/cafe_car/helpers.rb', line 159

def template_glob(glob)
  lookup_context.view_paths
    .flat_map { _1.send(:template_glob, glob) }
    .map { ActionView::TemplatePath.parse(_1) }
end

#title(object) ⇒ Object



36
37
38
39
40
# File 'lib/cafe_car/helpers.rb', line 36

def title(object)
  present(object).title.presence.tap do |title|
    content_for(:title, title)
  end
end

#ui(*args) ⇒ Object

Returns a new ‘Context`. Used for instantiating components: `ui.Button(:primary, “Submit”)`



4
5
6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/cafe_car/helpers.rb', line 4

def ui(*args, **, &)
  # For now, this must be defined in a helper instead of in the controller. Passing `view_context` or `helpers`
  # from the controller somehow breaks `capture`. `capture` will return the captured content, but the content
  # _also_ gets appended to the original output buffer.
  # This can be tested in a view by comparing the behavior of `= capture do` with
  # `= controller.view_context.capture do`; the latter outputs the content twice.
  if args.any?
    present(*args, **, &)
  elsif block_given?
    capture(&)
  else
    @ui ||= CafeCar::Context.new(self)
  end
end

#ui_class(names, *args, **opts) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/cafe_car/helpers.rb', line 19

def ui_class(names, *args, **opts)
  names  = [ *names ].map(&:camelize)
  name   = names.join("_")
  args.flatten!
  args.compact_blank!
  opts.compact_blank!
  opts.merge!(*args.extract!(Hash))

  flags = args.extract!(Symbol)
  flags |= opts.extract_if! { _1.is_a? Symbol }.keys
  flags.map! { "#{name}-#{_1}" }

  [ *name, *flags, *args, *opts.keys ].join(" ")
end

#view_url(view) ⇒ Object



73
74
75
76
77
78
# File 'lib/cafe_car/helpers.rb', line 73

def view_url(view)
  view = view.to_s
  params = request.params.merge(view:)
  params.delete(:view) if params[:view] == default_view
  url_for(params)
end