Reputation: 134
In one of my views, I rendered a table with a helper method, so the view (haml) looked like this:
= table do
- action "Add"
- column :id
- column :name
After I changed the helper and used the ViewComponent lib instead, I need to call it the following way:
= table do |t|
- t.action "Add"
- t.column :id
- t.column :name
I wondered if it's possible to convert the block in example 1 to the block in example 1 in a helper method, so I don't need to rewrite every view that uses a table.
The helper method would look like:
def table(*args, **kwargs, &block)
# ...
render TableComponent.new(*args, **kwargs, &new_block)
end
Upvotes: 2
Views: 316
Reputation: 9095
Let's simplify your example to this:
class Table
def initialize
@rows = []
end
def action(name)
@rows << "Action #{name}"
end
def column(name)
@rows << "Column #{name}"
end
def to_s
"Table:\n======\n#{@rows.join("\n")}"
end
end
def table(&block)
t = Table.new
block.call(t)
t
end
puts(
table do |t|
t.action "Add"
t.column :id
t.column :name
end
)
That gives:
Table:
======
Action Add
Column id
Column name
Now you want to do:
table do
action "Add"
column :id
column :name
end
So you want to have the body of the block be in the same context as the instance (e.g. like being in a Table instance), so:
def table(&block)
t = Table.new
t.instance_eval(&block)
t
end
(that's how most Domain Specific Languages are made :) )
Upvotes: 1