Skip to content

Commit 4421c2a

Browse files
committed
Implement #link_to_remove_nested_value helper in ActionView::Cocoon for handling value objects, analogous to Cocoon's #link_to_remove_association.
1 parent a8ce44d commit 4421c2a

File tree

2 files changed

+106
-0
lines changed

2 files changed

+106
-0
lines changed

lib/value_objects/action_view/cocoon.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ module ValueObjects
44
module ActionView
55

66
module Cocoon
7+
8+
def link_to_remove_nested_value(name, html_options = {}, &block)
9+
wrapper_class = html_options.delete(:wrapper_class)
10+
11+
html_options[:class] = [html_options[:class], 'remove_fields dynamic'].compact.join(' ')
12+
html_options[:'data-wrapper-class'] = wrapper_class if wrapper_class
13+
14+
name = capture(&block) if block_given?
15+
content_tag(:a, name, html_options)
16+
end
17+
718
end
819

920
end
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
load 'value_objects/action_view/cocoon.rb' # this module is dynamically loaded
2+
3+
RSpec.describe ValueObjects::ActionView::Cocoon do
4+
5+
class TestView < ActionView::Base
6+
end
7+
8+
let(:test_view) { TestView.new }
9+
let(:body) { Nokogiri::HTML(html).at('body') }
10+
let(:link) { body.at('a') }
11+
let(:link_text) { link.text }
12+
let(:link_href) { link.attribute('href')&.value }
13+
let(:link_class) { link.attribute('class')&.value }
14+
let(:link_wrapper_class) { link.attribute('data-wrapper-class')&.value }
15+
16+
describe '#link_to_remove_nested_value' do
17+
18+
shared_examples_for 'link_to_remove' do |options|
19+
20+
it 'renders the link correctly' do
21+
aggregate_failures do
22+
expect(body.children).to contain_exactly(link)
23+
expect(link_text).to eq(options[:text])
24+
expect(link_class).to eq(options[:class])
25+
expect(link_wrapper_class).to eq(options[:wrapper_class])
26+
expect(link_href).to eq(nil)
27+
end
28+
end
29+
30+
end
31+
32+
let(:html) { test_view.link_to_remove_nested_value(*args, &block) }
33+
let(:args) { [name] + [options].compact }
34+
let(:name) { nil }
35+
let(:options) { nil }
36+
let(:block) { nil }
37+
38+
include_examples 'link_to_remove', text: '', class: 'remove_fields dynamic'
39+
40+
context 'with name' do
41+
42+
let(:name) { 'Some text ...' }
43+
44+
include_examples 'link_to_remove', text: 'Some text ...', class: 'remove_fields dynamic'
45+
46+
context 'and block' do
47+
48+
let(:block) { -> { 'Block text' } }
49+
50+
include_examples 'link_to_remove', text: 'Block text', class: 'remove_fields dynamic'
51+
52+
end
53+
54+
end
55+
56+
context 'with class' do
57+
58+
let(:options) { { class: classes } }
59+
let(:classes) { 'foo bar' }
60+
61+
include_examples 'link_to_remove', text: '', class: 'foo bar remove_fields dynamic'
62+
63+
context 'as an array' do
64+
65+
let(:classes) { %w( foo bar ) }
66+
67+
include_examples 'link_to_remove', text: '', class: 'foo bar remove_fields dynamic'
68+
69+
end
70+
71+
end
72+
73+
context 'with wrapper_class' do
74+
75+
let(:options) { { wrapper_class: 'sub-fields' } }
76+
77+
include_examples 'link_to_remove', text: '', class: 'remove_fields dynamic', wrapper_class: 'sub-fields'
78+
79+
end
80+
81+
context 'with all args' do
82+
83+
let(:name) { 'text' }
84+
let(:options) { { class: 'bar foo', wrapper_class: 'fields' } }
85+
86+
include_examples 'link_to_remove', text: 'text', class: 'bar foo remove_fields dynamic', wrapper_class: 'fields'
87+
88+
end
89+
90+
end
91+
92+
end
93+
94+
# cleanup to avoid interfering with other specs
95+
ValueObjects::ActionView.send(:remove_const, :Cocoon)

0 commit comments

Comments
 (0)