line-message-builder 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/.rubocop.yml +5 -0
- data/CHANGELOG.md +20 -0
- data/CLAUDE.md +124 -0
- data/README.md +24 -16
- data/claudekit.json +11 -0
- data/docs/rubrics/rdoc.md +169 -0
- data/lib/line/message/builder/actions/message.rb +47 -26
- data/lib/line/message/builder/actions/postback.rb +56 -26
- data/lib/line/message/builder/actions/uri.rb +139 -0
- data/lib/line/message/builder/actions.rb +6 -3
- data/lib/line/message/builder/base.rb +92 -67
- data/lib/line/message/builder/container.rb +55 -60
- data/lib/line/message/builder/context.rb +51 -72
- data/lib/line/message/builder/flex/actionable.rb +53 -32
- data/lib/line/message/builder/flex/box.rb +342 -79
- data/lib/line/message/builder/flex/bubble.rb +73 -46
- data/lib/line/message/builder/flex/builder.rb +39 -28
- data/lib/line/message/builder/flex/button.rb +90 -42
- data/lib/line/message/builder/flex/carousel.rb +48 -20
- data/lib/line/message/builder/flex/icon.rb +152 -0
- data/lib/line/message/builder/flex/image.rb +95 -33
- data/lib/line/message/builder/flex/partial.rb +47 -49
- data/lib/line/message/builder/flex/position.rb +187 -100
- data/lib/line/message/builder/flex/separator.rb +49 -6
- data/lib/line/message/builder/flex/size.rb +67 -47
- data/lib/line/message/builder/flex/span.rb +106 -32
- data/lib/line/message/builder/flex/text.rb +166 -54
- data/lib/line/message/builder/flex.rb +26 -23
- data/lib/line/message/builder/quick_reply.rb +174 -4
- data/lib/line/message/builder/text.rb +70 -3
- data/lib/line/message/builder/version.rb +1 -1
- data/lib/line/message/builder.rb +14 -11
- data/lib/line/message/rspec/matchers/have_flex_bubble.rb +1 -1
- data/lib/line/message/rspec/matchers/have_flex_component.rb +16 -6
- data/lib/line/message/rspec/matchers/have_flex_message.rb +1 -1
- data/lib/line/message/rspec/matchers/have_flex_separator.rb +1 -1
- data/lib/line/message/rspec/matchers/have_quick_reply.rb +1 -1
- data/lib/line/message/rspec/matchers/have_text_message.rb +1 -1
- data/llm.txt +276 -35
- data/release-please-config.json +3 -1
- metadata +9 -3
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Line
|
|
4
|
+
module Message
|
|
5
|
+
module Builder
|
|
6
|
+
module Flex
|
|
7
|
+
# Represents an "icon" component in a LINE Flex Message.
|
|
8
|
+
#
|
|
9
|
+
# Icons render a small image that decorates the text next to them. They are
|
|
10
|
+
# the standard way to build rating stars, labelled metadata rows, and other
|
|
11
|
+
# icon-and-text pairs.
|
|
12
|
+
#
|
|
13
|
+
# An icon can only be placed in a box whose +layout+ is +:baseline+. Unlike
|
|
14
|
+
# Image, an icon cannot have an action attached to it.
|
|
15
|
+
#
|
|
16
|
+
# == Example: Rating stars beside a score
|
|
17
|
+
#
|
|
18
|
+
# Line::Message::Builder.with do
|
|
19
|
+
# flex alt_text: "Review" do
|
|
20
|
+
# bubble do
|
|
21
|
+
# body do
|
|
22
|
+
# box layout: :baseline do
|
|
23
|
+
# icon "https://example.com/star_on.png", size: :sm
|
|
24
|
+
# icon "https://example.com/star_on.png", size: :sm
|
|
25
|
+
# icon "https://example.com/star_off.png", size: :sm
|
|
26
|
+
# text "3.0", size: :sm, margin: :md
|
|
27
|
+
# end
|
|
28
|
+
# end
|
|
29
|
+
# end
|
|
30
|
+
# end
|
|
31
|
+
# end
|
|
32
|
+
#
|
|
33
|
+
# === Example: Following the reader's font size
|
|
34
|
+
#
|
|
35
|
+
# box layout: :baseline do
|
|
36
|
+
# icon "https://example.com/pin.png", scaling: true
|
|
37
|
+
# text "Taipei", scaling: true
|
|
38
|
+
# end
|
|
39
|
+
#
|
|
40
|
+
# See also:
|
|
41
|
+
# - https://developers.line.biz/en/reference/messaging-api/#icon
|
|
42
|
+
# - Position::Margin for +margin+ property
|
|
43
|
+
# - Position::Offset for offset properties
|
|
44
|
+
# - Size::Shared for common +size+ keywords (e.g., +:sm+, +:xl+)
|
|
45
|
+
class Icon < Line::Message::Builder::Base
|
|
46
|
+
include Position::Margin # Adds `margin` option.
|
|
47
|
+
include Position::Offset # Adds offset options.
|
|
48
|
+
include Size::Shared # Adds `size` option (e.g., :sm, :md, :xl).
|
|
49
|
+
|
|
50
|
+
# The URL of the icon image (must be HTTPS). This is a required attribute.
|
|
51
|
+
attr_reader :url
|
|
52
|
+
|
|
53
|
+
# :method: aspect_ratio
|
|
54
|
+
# :call-seq:
|
|
55
|
+
# aspect_ratio() -> String or nil
|
|
56
|
+
# aspect_ratio(value) -> String
|
|
57
|
+
#
|
|
58
|
+
# Sets or gets the aspect ratio of the icon (width:height).
|
|
59
|
+
#
|
|
60
|
+
# [value]
|
|
61
|
+
# The aspect ratio string (e.g., <code>"1:1"</code>, <code>"2:1"</code>).
|
|
62
|
+
# Default is <code>"1:1"</code>
|
|
63
|
+
option :aspect_ratio, default: nil # API key: aspectRatio
|
|
64
|
+
|
|
65
|
+
# :method: scaling
|
|
66
|
+
# :call-seq:
|
|
67
|
+
# scaling() -> Boolean or nil
|
|
68
|
+
# scaling(value) -> Boolean
|
|
69
|
+
#
|
|
70
|
+
# Sets or gets whether the icon size follows the font size setting of the
|
|
71
|
+
# LINE app.
|
|
72
|
+
#
|
|
73
|
+
# [value]
|
|
74
|
+
# +true+ to scale the icon, +false+ (default) to keep it fixed
|
|
75
|
+
option :scaling, default: nil
|
|
76
|
+
|
|
77
|
+
# Initializes a new Flex Message Icon component.
|
|
78
|
+
#
|
|
79
|
+
# [url]
|
|
80
|
+
# The HTTPS URL of the icon image (required)
|
|
81
|
+
# [context]
|
|
82
|
+
# An optional context for the builder (default: +nil+)
|
|
83
|
+
# [options]
|
|
84
|
+
# A hash of options to set instance variables (e.g., +:size+,
|
|
85
|
+
# +:aspect_ratio+, and options from included modules)
|
|
86
|
+
# [block]
|
|
87
|
+
# An optional block for further configuration
|
|
88
|
+
#
|
|
89
|
+
# Raises RequiredError if +url+ is +nil+ when building the message.
|
|
90
|
+
#
|
|
91
|
+
# == Example
|
|
92
|
+
#
|
|
93
|
+
# Line::Message::Builder::Flex::Icon.new(
|
|
94
|
+
# "https://example.com/star.png",
|
|
95
|
+
# size: :sm
|
|
96
|
+
# )
|
|
97
|
+
def initialize(url, context: nil, **options, &)
|
|
98
|
+
@url = url # The icon URL is mandatory.
|
|
99
|
+
|
|
100
|
+
super(context: context, **options, &)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
# :nodoc:
|
|
106
|
+
def to_api # rubocop:disable Metrics/MethodLength
|
|
107
|
+
raise RequiredError, "url is required for an icon component" if url.nil?
|
|
108
|
+
|
|
109
|
+
{
|
|
110
|
+
type: "icon",
|
|
111
|
+
url: url,
|
|
112
|
+
# Position::Margin
|
|
113
|
+
margin: margin,
|
|
114
|
+
# Position::Offset
|
|
115
|
+
position: position,
|
|
116
|
+
offsetTop: offset_top,
|
|
117
|
+
offsetBottom: offset_bottom,
|
|
118
|
+
offsetStart: offset_start,
|
|
119
|
+
offsetEnd: offset_end,
|
|
120
|
+
# Size::Shared
|
|
121
|
+
size: size,
|
|
122
|
+
aspectRatio: aspect_ratio, # From option (maps to API key)
|
|
123
|
+
scaling: scaling # From option
|
|
124
|
+
}.compact
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# :nodoc:
|
|
128
|
+
def to_sdkv2 # rubocop:disable Metrics/MethodLength
|
|
129
|
+
raise RequiredError, "url is required for an icon component" if url.nil?
|
|
130
|
+
|
|
131
|
+
{
|
|
132
|
+
type: "icon",
|
|
133
|
+
url: url,
|
|
134
|
+
# Position::Margin
|
|
135
|
+
margin: margin,
|
|
136
|
+
# Position::Offset
|
|
137
|
+
position: position,
|
|
138
|
+
offset_top: offset_top,
|
|
139
|
+
offset_bottom: offset_bottom,
|
|
140
|
+
offset_start: offset_start,
|
|
141
|
+
offset_end: offset_end,
|
|
142
|
+
# Size::Shared
|
|
143
|
+
size: size,
|
|
144
|
+
aspect_ratio: aspect_ratio, # From option (maps to API key)
|
|
145
|
+
scaling: scaling # From option
|
|
146
|
+
}.compact
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
end
|
|
@@ -8,11 +8,12 @@ module Line
|
|
|
8
8
|
#
|
|
9
9
|
# Images are specified by a URL and can be included in various parts of a
|
|
10
10
|
# Flex Message, such as a box, a bubble's hero section, etc. They offer
|
|
11
|
-
# several properties to control their appearance, including
|
|
12
|
-
#
|
|
13
|
-
#
|
|
11
|
+
# several properties to control their appearance, including +size+,
|
|
12
|
+
# +aspect_ratio+, +aspect_mode+ and +background_color+. An image can also
|
|
13
|
+
# have an action to make it tappable.
|
|
14
|
+
#
|
|
15
|
+
# == Example
|
|
14
16
|
#
|
|
15
|
-
# @example Creating an image component within a box
|
|
16
17
|
# Line::Message::Builder.with do
|
|
17
18
|
# flex alt_text: "Image Example" do
|
|
18
19
|
# bubble do
|
|
@@ -27,14 +28,27 @@ module Line
|
|
|
27
28
|
# end
|
|
28
29
|
# end
|
|
29
30
|
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
31
|
+
# === Example: Playing an animated image on a tinted backdrop
|
|
32
|
+
#
|
|
33
|
+
# Line::Message::Builder.with do
|
|
34
|
+
# flex alt_text: "Image Example" do
|
|
35
|
+
# bubble do
|
|
36
|
+
# hero_image "https://example.com/loading.png",
|
|
37
|
+
# animated: true,
|
|
38
|
+
# background_color: "#FFFFFF"
|
|
39
|
+
# end
|
|
40
|
+
# end
|
|
41
|
+
# end
|
|
42
|
+
#
|
|
43
|
+
# See also:
|
|
44
|
+
# - https://developers.line.biz/en/reference/messaging-api/#image
|
|
45
|
+
# - Actionable for making the image tappable
|
|
46
|
+
# - Position::Horizontal for +align+ property
|
|
47
|
+
# - Position::Vertical for +gravity+ property
|
|
48
|
+
# - Position::Margin for +margin+ property
|
|
49
|
+
# - Position::Offset for offset properties
|
|
50
|
+
# - Size::Flex for +flex+ sizing property
|
|
51
|
+
# - Size::Image for +size+, +aspect_ratio+, and +aspect_mode+ properties
|
|
38
52
|
class Image < Line::Message::Builder::Base
|
|
39
53
|
include Actionable # Enables defining an action for the image.
|
|
40
54
|
include Position::Horizontal # Adds `align` option for horizontal alignment.
|
|
@@ -44,35 +58,77 @@ module Line
|
|
|
44
58
|
include Size::Flex # Adds `flex` option for sizing within a parent box.
|
|
45
59
|
include Size::Image # Adds image-specific sizing options like `size`, `aspect_ratio`, `aspect_mode`.
|
|
46
60
|
|
|
47
|
-
#
|
|
48
|
-
# @return [String] The URL of the image. Must be HTTPS.
|
|
49
|
-
# This is a required attribute.
|
|
61
|
+
# The URL of the image (must be HTTPS). This is a required attribute.
|
|
50
62
|
attr_reader :url
|
|
51
63
|
|
|
52
|
-
#
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
64
|
+
# :method: aspect_ratio
|
|
65
|
+
# :call-seq:
|
|
66
|
+
# aspect_ratio() -> String or nil
|
|
67
|
+
# aspect_ratio(value) -> String
|
|
68
|
+
#
|
|
69
|
+
# Sets or gets the aspect ratio of the image (width:height).
|
|
70
|
+
#
|
|
71
|
+
# [value]
|
|
72
|
+
# The aspect ratio string (e.g., <code>"1:1"</code>, <code>"16:9"</code>,
|
|
73
|
+
# <code>"20:13"</code>). Default is <code>"1:1"</code>.
|
|
57
74
|
option :aspect_ratio, default: nil
|
|
58
75
|
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
#
|
|
76
|
+
# :method: aspect_mode
|
|
77
|
+
# :call-seq:
|
|
78
|
+
# aspect_mode() -> Symbol or nil
|
|
79
|
+
# aspect_mode(value) -> Symbol
|
|
80
|
+
#
|
|
81
|
+
# Sets or gets how the image should be displayed within the area defined by +aspect_ratio+.
|
|
82
|
+
#
|
|
83
|
+
# [value]
|
|
84
|
+
# The aspect mode (can be +:cover+ (default) or +:fit+)
|
|
64
85
|
option :aspect_mode, default: nil # :cover, :fit
|
|
65
86
|
|
|
87
|
+
# :method: background_color
|
|
88
|
+
# :call-seq:
|
|
89
|
+
# background_color() -> String or nil
|
|
90
|
+
# background_color(value) -> String
|
|
91
|
+
#
|
|
92
|
+
# Sets or gets the background color shown behind the image.
|
|
93
|
+
#
|
|
94
|
+
# [value]
|
|
95
|
+
# Hexadecimal color code (e.g., <code>"#RRGGBB"</code>)
|
|
96
|
+
option :background_color, default: nil # API key: backgroundColor
|
|
97
|
+
|
|
98
|
+
# :method: animated
|
|
99
|
+
# :call-seq:
|
|
100
|
+
# animated() -> Boolean or nil
|
|
101
|
+
# animated(value) -> Boolean
|
|
102
|
+
#
|
|
103
|
+
# Sets or gets whether an animated image (APNG) is played back. A single
|
|
104
|
+
# message may mark at most 10 images as animated, and frames larger than
|
|
105
|
+
# 300 KB are not played.
|
|
106
|
+
#
|
|
107
|
+
# [value]
|
|
108
|
+
# +true+ to play the animation, +false+ (default) to show a still frame
|
|
109
|
+
option :animated, default: nil
|
|
110
|
+
|
|
66
111
|
# Initializes a new Flex Message Image component.
|
|
67
112
|
#
|
|
68
|
-
#
|
|
69
|
-
#
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
113
|
+
# [url]
|
|
114
|
+
# The HTTPS URL of the image (required)
|
|
115
|
+
# [context]
|
|
116
|
+
# An optional context for the builder (default: +nil+)
|
|
117
|
+
# [options]
|
|
118
|
+
# A hash of options to set instance variables (e.g., +:aspect_ratio+,
|
|
119
|
+
# +:aspect_mode+, +:size+, and options from included modules)
|
|
120
|
+
# [block]
|
|
121
|
+
# An optional block, typically used to define an action for the image
|
|
122
|
+
#
|
|
123
|
+
# Raises RequiredError if +url+ is +nil+ when building the message.
|
|
124
|
+
#
|
|
125
|
+
# == Example
|
|
126
|
+
#
|
|
127
|
+
# image = Line::Message::Builder::Flex::Image.new(
|
|
128
|
+
# "https://example.com/image.png",
|
|
129
|
+
# aspect_ratio: "16:9",
|
|
130
|
+
# aspect_mode: :cover
|
|
131
|
+
# )
|
|
76
132
|
def initialize(url, context: nil, **options, &)
|
|
77
133
|
@url = url # The image URL is mandatory.
|
|
78
134
|
|
|
@@ -81,6 +137,7 @@ module Line
|
|
|
81
137
|
|
|
82
138
|
private
|
|
83
139
|
|
|
140
|
+
# :nodoc:
|
|
84
141
|
def to_api # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
85
142
|
raise RequiredError, "url is required for an image component" if url.nil?
|
|
86
143
|
|
|
@@ -104,11 +161,14 @@ module Line
|
|
|
104
161
|
size: size,
|
|
105
162
|
aspectRatio: aspect_ratio, # From option
|
|
106
163
|
aspectMode: aspect_mode, # From option
|
|
164
|
+
backgroundColor: background_color, # From option (maps to API key)
|
|
165
|
+
animated: animated, # From option
|
|
107
166
|
# Actionable
|
|
108
167
|
action: action&.to_h # From Actionable module
|
|
109
168
|
}.compact
|
|
110
169
|
end
|
|
111
170
|
|
|
171
|
+
# :nodoc:
|
|
112
172
|
def to_sdkv2 # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
|
113
173
|
raise RequiredError, "url is required for an image component" if url.nil?
|
|
114
174
|
|
|
@@ -132,6 +192,8 @@ module Line
|
|
|
132
192
|
size: size,
|
|
133
193
|
aspect_ratio: aspect_ratio, # From option
|
|
134
194
|
aspect_mode: aspect_mode, # From option
|
|
195
|
+
background_color: background_color, # From option (maps to API key)
|
|
196
|
+
animated: animated, # From option
|
|
135
197
|
# Actionable
|
|
136
198
|
action: action&.to_h # From Actionable module
|
|
137
199
|
}.compact
|
|
@@ -4,19 +4,20 @@ module Line
|
|
|
4
4
|
module Message
|
|
5
5
|
module Builder
|
|
6
6
|
module Flex
|
|
7
|
-
# The
|
|
8
|
-
# (like
|
|
9
|
-
# by creating classes that inherit from
|
|
7
|
+
# The HasPartial module provides functionality for Flex Message components
|
|
8
|
+
# (like Box, Bubble) to render reusable "partials". Partials are defined
|
|
9
|
+
# by creating classes that inherit from Partial.
|
|
10
10
|
#
|
|
11
|
-
# Including this module into a component class gives it the
|
|
11
|
+
# Including this module into a component class gives it the +partial!+ method.
|
|
12
|
+
#
|
|
13
|
+
# == Example
|
|
12
14
|
#
|
|
13
|
-
# @example Defining and using a partial
|
|
14
15
|
# # Define a reusable partial
|
|
15
16
|
# class MyButtonPartial < Line::Message::Builder::Flex::Partial
|
|
16
17
|
# def call
|
|
17
|
-
# #
|
|
18
|
+
# # +button+ method is available from the context (e.g., a Box)
|
|
18
19
|
# button style: :primary do
|
|
19
|
-
# #
|
|
20
|
+
# # +data+ and +label+ are available from <code>context.assigns</code>
|
|
20
21
|
# postback data, label: label
|
|
21
22
|
# end
|
|
22
23
|
# end
|
|
@@ -33,20 +34,22 @@ module Line
|
|
|
33
34
|
# end
|
|
34
35
|
# end
|
|
35
36
|
#
|
|
36
|
-
#
|
|
37
|
+
# See also:
|
|
38
|
+
# - Partial
|
|
37
39
|
module HasPartial
|
|
38
|
-
# Renders a given
|
|
40
|
+
# Renders a given Partial class within the current component's context.
|
|
41
|
+
#
|
|
42
|
+
# This method temporarily makes the provided +assigns+ available to the
|
|
43
|
+
# partial through the <code>context.assigns</code> mechanism. After the partial's
|
|
44
|
+
# +call+ method completes, the original <code>context.assigns</code> are restored.
|
|
39
45
|
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
46
|
+
# [partial_class]
|
|
47
|
+
# The class of the partial to render. Must be a subclass of Partial.
|
|
48
|
+
# [assigns]
|
|
49
|
+
# A hash of key-value pairs that will be made available as +assigns+
|
|
50
|
+
# within the partial's +call+ method.
|
|
43
51
|
#
|
|
44
|
-
#
|
|
45
|
-
# subclass of {Partial}.
|
|
46
|
-
# @param assigns [Hash] A hash of key-value pairs that will be made
|
|
47
|
-
# available as `assigns` within the partial's `call` method.
|
|
48
|
-
# @return [void]
|
|
49
|
-
# @raise [ArgumentError] if `partial_class` is not a subclass of {Partial}.
|
|
52
|
+
# Raises ArgumentError if +partial_class+ is not a subclass of Partial.
|
|
50
53
|
def partial!(partial_class, **assigns)
|
|
51
54
|
unless partial_class < Partial
|
|
52
55
|
raise ArgumentError,
|
|
@@ -62,60 +65,55 @@ module Line
|
|
|
62
65
|
end
|
|
63
66
|
end
|
|
64
67
|
|
|
65
|
-
# The
|
|
68
|
+
# The Partial class is an abstract base for creating reusable snippets
|
|
66
69
|
# of Flex Message content. To define a partial, create a new class that
|
|
67
|
-
# inherits from
|
|
70
|
+
# inherits from Partial and implements the +call+ instance method.
|
|
68
71
|
#
|
|
69
|
-
# Within the
|
|
70
|
-
# DSL methods (e.g.,
|
|
72
|
+
# Within the +call+ method, you can use the standard Flex Message builder
|
|
73
|
+
# DSL methods (e.g., +text+, +box+, +button+) as if you were directly inside
|
|
71
74
|
# the component where the partial is being rendered. This is possible because
|
|
72
|
-
# the
|
|
73
|
-
# instance that is rendering it (passed as
|
|
75
|
+
# the Partial instance delegates unknown method calls to the component
|
|
76
|
+
# instance that is rendering it (passed as +context+ during initialization).
|
|
74
77
|
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
78
|
+
# Subclass and implement +call+ to create a concrete partial.
|
|
79
|
+
#
|
|
80
|
+
# See also:
|
|
81
|
+
# - HasPartial for how to render partials
|
|
77
82
|
class Partial
|
|
78
83
|
# Initializes a new Partial instance.
|
|
79
|
-
# This is typically called by the
|
|
84
|
+
# This is typically called by the HasPartial#partial! method.
|
|
80
85
|
#
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
# the DSL methods (like
|
|
86
|
+
# [context]
|
|
87
|
+
# The component instance (e.g., Box, Bubble) within which this partial
|
|
88
|
+
# is being rendered. This context provides the DSL methods (like +text+,
|
|
89
|
+
# +box+) used in the partial's +call+ method.
|
|
84
90
|
def initialize(context:)
|
|
85
91
|
@context = context # The component (e.g., Box, Bubble) rendering this partial
|
|
86
92
|
end
|
|
87
93
|
|
|
88
94
|
# This method must be implemented by subclasses to define the content of
|
|
89
95
|
# the partial. Inside this method, use the Flex Message builder DSL methods
|
|
90
|
-
# (e.g.,
|
|
91
|
-
# rendering context.
|
|
96
|
+
# (e.g., <code>text "Hello"</code>, <code>button { ... }</code>) which will be
|
|
97
|
+
# delegated to the rendering context.
|
|
98
|
+
#
|
|
99
|
+
# Any arguments passed to +partial!+ as +assigns+ are available via
|
|
100
|
+
# <code>context.assigns</code> or directly if the rendering context's +method_missing+
|
|
101
|
+
# handles +assigns+ lookup (as Line::Message::Builder::Context does).
|
|
92
102
|
#
|
|
93
|
-
#
|
|
94
|
-
#
|
|
95
|
-
# handles `assigns` lookup (as {Line::Message::Builder::Context} does).
|
|
103
|
+
# Arguments passed from the +partial!+ call's +assigns+ can be explicitly defined
|
|
104
|
+
# as parameters here, or accessed via <code>context.assigns</code>.
|
|
96
105
|
#
|
|
97
|
-
#
|
|
98
|
-
# can be explicitly defined as parameters here, or accessed via `context.assigns`.
|
|
99
|
-
# @raise [NotImplementedError] if a subclass does not implement this method.
|
|
106
|
+
# Raises NotImplementedError if a subclass does not implement this method.
|
|
100
107
|
def call(*)
|
|
101
108
|
raise NotImplementedError,
|
|
102
109
|
"The #{self.class.name} class must implement the #call method to define its content."
|
|
103
110
|
end
|
|
104
111
|
|
|
105
|
-
#
|
|
106
|
-
# Part of Ruby's dynamic method dispatch. It's overridden here to declare
|
|
107
|
-
# that instances of `Partial` can respond to methods to which the
|
|
108
|
-
# wrapped `@context` object responds.
|
|
109
|
-
def respond_to_missing?(method_name, include_private = false)
|
|
112
|
+
def respond_to_missing?(method_name, include_private = false) # :nodoc:
|
|
110
113
|
@context.respond_to?(method_name, include_private) || super
|
|
111
114
|
end
|
|
112
115
|
|
|
113
|
-
#
|
|
114
|
-
# Handles calls to methods not explicitly defined on the `Partial` class
|
|
115
|
-
# by delegating them to the wrapped `@context` object (the rendering component).
|
|
116
|
-
# This allows the `call` method of a partial to use DSL methods like `text`,
|
|
117
|
-
# `box`, `button`, etc., as if they were defined directly in the partial.
|
|
118
|
-
def method_missing(method_name, ...)
|
|
116
|
+
def method_missing(method_name, ...) # :nodoc:
|
|
119
117
|
if @context.respond_to?(method_name)
|
|
120
118
|
@context.public_send(method_name, ...)
|
|
121
119
|
else
|