interview 0.0.1 → 0.0.6

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/interview.gemspec +4 -0
  3. data/lib/generators/interview/install/install_generator.rb +47 -0
  4. data/lib/generators/interview/install/templates/32px.png +0 -0
  5. data/lib/generators/interview/install/templates/40px.png +0 -0
  6. data/lib/generators/interview/install/templates/application.js +22 -0
  7. data/lib/generators/interview/install/templates/bootstrap_interview.css.scss +98 -0
  8. data/lib/generators/interview/install/templates/ckeditor_config.js +19 -0
  9. data/lib/generators/interview/install/templates/colors.css.scss +2 -0
  10. data/lib/generators/interview/install/templates/defaults_de.yml +204 -0
  11. data/lib/generators/interview/install/templates/interview.js.coffee +72 -0
  12. data/lib/generators/interview/install/templates/interview.rb +4 -0
  13. data/lib/generators/interview/install/templates/jstree.css +916 -0
  14. data/lib/generators/interview/install/templates/jstree.js +5892 -0
  15. data/lib/generators/interview/install/templates/missing_large.png +0 -0
  16. data/lib/generators/interview/install/templates/missing_medium.png +0 -0
  17. data/lib/generators/interview/install/templates/missing_thumb.png +0 -0
  18. data/lib/generators/interview/install/templates/throbber.gif +0 -0
  19. data/lib/generators/interview/install/templates/views_defaults_de.yml +8 -0
  20. data/lib/generators/interview/view_control/templates/card.rb +6 -0
  21. data/lib/generators/interview/view_control/templates/form.rb +6 -0
  22. data/lib/generators/interview/view_control/templates/list.rb +6 -0
  23. data/lib/generators/interview/view_control/view_control_generator.rb +34 -0
  24. data/lib/interview/actionbar.rb +38 -0
  25. data/lib/interview/association_attribute.rb +33 -0
  26. data/lib/interview/association_list_attribute.rb +36 -0
  27. data/lib/interview/association_methods.rb +23 -0
  28. data/lib/interview/attribute.rb +141 -0
  29. data/lib/interview/boolean_attribute.rb +59 -0
  30. data/lib/interview/breadcrumbs.rb +21 -0
  31. data/lib/interview/container_attribute.rb +30 -0
  32. data/lib/interview/control.rb +73 -0
  33. data/lib/interview/control_def.rb +36 -0
  34. data/lib/interview/date_attribute.rb +20 -0
  35. data/lib/interview/datetime_attribute.rb +20 -0
  36. data/lib/interview/decimal_attribute.rb +10 -0
  37. data/lib/interview/dropdown.rb +26 -0
  38. data/lib/interview/form.rb +69 -0
  39. data/lib/interview/form_errors.rb +22 -0
  40. data/lib/interview/grid.rb +53 -0
  41. data/lib/interview/has_controls.rb +43 -0
  42. data/lib/interview/hidden_attribute.rb +15 -0
  43. data/lib/interview/html_control.rb +15 -0
  44. data/lib/interview/html_text_attribute.rb +19 -0
  45. data/lib/interview/image_attribute.rb +34 -0
  46. data/lib/interview/integer_attribute.rb +5 -0
  47. data/lib/interview/link.rb +129 -0
  48. data/lib/interview/list.rb +21 -0
  49. data/lib/interview/navigation.rb +55 -0
  50. data/lib/interview/navigation_item.rb +26 -0
  51. data/lib/interview/nested_form.rb +51 -0
  52. data/lib/interview/nested_form_add_link.rb +80 -0
  53. data/lib/interview/nested_form_remove_link.rb +28 -0
  54. data/lib/interview/object_context.rb +17 -0
  55. data/lib/interview/option_attribute.rb +74 -0
  56. data/lib/interview/polymorphic_add_link.rb +28 -0
  57. data/lib/interview/space.rb +18 -0
  58. data/lib/interview/string_attribute.rb +5 -0
  59. data/lib/interview/tab.rb +21 -0
  60. data/lib/interview/tab_box.rb +29 -0
  61. data/lib/interview/text.rb +15 -0
  62. data/lib/interview/text_attribute.rb +21 -0
  63. data/lib/interview/tooltip.rb +38 -0
  64. data/lib/interview/tree.rb +33 -0
  65. data/lib/interview/version.rb +1 -1
  66. data/lib/interview/view.rb +87 -0
  67. data/lib/interview.rb +196 -0
  68. metadata +107 -2
@@ -0,0 +1,69 @@
1
+ module Interview
2
+ class Form < Control
3
+ include HasControls
4
+
5
+ attr_accessor :skip_submit, :multi_create, :align, :redirect_to
6
+ attr_reader :form_builder
7
+
8
+ def attribute_modus
9
+ return :write
10
+ end
11
+
12
+ def render # todo: Aufräumen
13
+ object = find_attribute!(:object)
14
+ model = object.class.lookup_ancestors.last.model_name.singular # todo
15
+ # if object.class.superclass.name == 'ActiveRecord::Base'
16
+ # model = object.class.name.underscore
17
+ # else
18
+ # model = object.class.superclass.name.underscore
19
+ # end
20
+ if object.id
21
+ url = h.send("#{model}_path", object)
22
+ else
23
+ url = h.send("#{model.pluralize}_path")
24
+ end
25
+ opts = {as: model.to_sym, url: url, role: 'form', html: {}}
26
+ opts[:html][:class] = 'form-horizontal' if @align == 'horizontal'
27
+ opts[:html][:class] = 'form-inline' if @align == 'inline'
28
+ html = Builder::XmlMarkup.new
29
+ html << h.form_for(object, opts) do |form_builder|
30
+ @form_builder = form_builder
31
+ form_html = Builder::XmlMarkup.new
32
+ form_html << FormErrors.new(parent: self).render
33
+ if @redirect_to == :parent and Object.const_defined? 'Gretel'
34
+ form_html << h.hidden_field_tag('redirect_to', h.parent_breadcrumb.url)
35
+ end
36
+
37
+ @controls.each do |control|
38
+ form_html << control.render
39
+ form_html.text! ' ' if @align == 'inline'
40
+ end
41
+
42
+ if not @skip_submit
43
+ if @align == 'horizontal'
44
+ form_html.div class: 'form-group' do
45
+ form_html.div class: 'col-sm-offset-3 col-sm-9' do
46
+ form_html << form_builder.submit(class: 'btn btn-primary')
47
+ if @multi_create || find_attribute(:multi_create)
48
+ form_html.text! ' '
49
+ form_html << h.check_box_tag('new_record', '1', true)
50
+ form_html.text! ' und weiteren Datesatz'
51
+ end
52
+ end
53
+ end
54
+ else
55
+ form_html << form_builder.submit(class: 'btn btn-primary')
56
+ if @multi_create || find_attribute(:multi_create)
57
+ form_html.text! ' '
58
+ form_html << h.check_box_tag('new_record', '1', true)
59
+ form_html.text! ' und weiteren Datesatz'
60
+ end
61
+ end
62
+ end
63
+ form_html.target!.html_safe
64
+ end
65
+ return html.target!
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,22 @@
1
+ module Interview
2
+ class FormErrors < Control
3
+
4
+ def render
5
+ object = find_attribute!(:object)
6
+
7
+ html = Builder::XmlMarkup.new
8
+ if object.errors.any?
9
+ html.div class: 'error_explanation!' do
10
+ html.h2 "#{pluralize(object.errors.count, 'error')} prohibited this article from being saved:"
11
+ html.ul do
12
+ object.errors.full_messages.each do |msg|
13
+ html.li msg
14
+ end
15
+ end
16
+ end
17
+ end
18
+ return html.target!
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,53 @@
1
+ module Interview
2
+ class Grid < Control
3
+ include HasControls
4
+
5
+ attr_accessor :objects, :sortable
6
+ attr_reader :object
7
+
8
+ def render
9
+ objects = @objects || find_attribute!(:objects)
10
+ @object = find_attribute!(:object)
11
+ sortable_id = "sortable_#{@object.class.model_name.plural}" if @sortable
12
+ html = Builder::XmlMarkup.new
13
+ html.table class: 'table' do
14
+ html.thead do
15
+ html.tr do
16
+ html.th '' if @sortable
17
+ @controls.each do |control|
18
+ html.th do
19
+ html << control.caption
20
+ end
21
+ end
22
+ end
23
+ end
24
+ html_opts = {}
25
+ html_opts[:id] = sortable_id if @sortable
26
+ html.tbody html_opts do
27
+ objects.each do |object|
28
+ @object = object
29
+ html_opts = {}
30
+ html_opts[:id] = "#{sortable_id}_#{object.id}" if @sortable
31
+ html.tr html_opts do
32
+ if @sortable
33
+ html.td do
34
+ html.span '', class: 'handle glyphicon glyphicon-resize-vertical'
35
+ end
36
+ end
37
+ @controls.each do |control|
38
+ html.td do
39
+ html << control.render
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ if objects.empty?
47
+ html.p "Keine #{@object.class.model_name.human(count: 2)} vorhanden.", class: 'text-center text-muted'
48
+ end
49
+ return html.target!
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,43 @@
1
+ module HasControls
2
+
3
+ attr_reader :controls
4
+
5
+ def initialize(params={})
6
+ super
7
+ @controls = self.class.definition.build_controls_for self
8
+ end
9
+
10
+ def add_control(control, &block)
11
+ control.parent = self
12
+ yield(control) if block_given?
13
+ @controls << control
14
+ end
15
+
16
+ def add_controls(controls)
17
+ controls.each { |control| control.parent = self }
18
+ @controls += controls
19
+ end
20
+
21
+ def siblings
22
+ return @controls.map do |control|
23
+ if control.respond_to? :siblings
24
+ [control] + control.siblings
25
+ else
26
+ control
27
+ end
28
+ end.flatten
29
+ end
30
+
31
+ def self.included(mod)
32
+ mod.extend ClassMethods
33
+ end
34
+
35
+ module ClassMethods
36
+
37
+ def control(klass, params={}, &block)
38
+ @definition.control(klass, params, &block)
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,15 @@
1
+ module Interview
2
+ class HiddenAttribute < Attribute
3
+
4
+ def render_write
5
+ form_builder.hidden_field @method
6
+ end
7
+
8
+ protected
9
+
10
+ def render_form_style
11
+ return render_write
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Interview
2
+ class HtmlControl < Control
3
+
4
+ def initialize(params={}, &block)
5
+ super
6
+ @html = Builder::XmlMarkup.new
7
+ yield @html
8
+ end
9
+
10
+ def render
11
+ return @html.target!
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module Interview
2
+ class HtmlTextAttribute < Attribute
3
+
4
+ attr_accessor :plain_text, :cut
5
+
6
+ def render_read
7
+ return '' if value.nil?
8
+ val = value
9
+ val.gsub! /<.+?>/, ' ' if @plain_text
10
+ val = val[0..29] + '...' if @cut and val.size > 30
11
+ return val.html_safe
12
+ end
13
+
14
+ def render_write
15
+ form_builder.cktext_area @method, class: 'form-control'
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,34 @@
1
+ module Interview
2
+ class ImageAttribute < Attribute
3
+
4
+ attr_accessor :image_style, :hide_if_not_exists
5
+
6
+ def render_read
7
+ return '' if value.nil?
8
+ image_style = @image_style || :thumb
9
+ if not value.exists? and @hide_if_not_exists
10
+ return ''
11
+ else
12
+ return h.image_tag value.url(image_style)
13
+ end
14
+ end
15
+
16
+ def render_write
17
+ object = find_attribute(:object)
18
+ image = object.send @method
19
+
20
+ html = Builder::XmlMarkup.new
21
+ if image.exists? and @image_style
22
+ html.br
23
+ html << h.image_tag(image.url(@image_style))
24
+ end
25
+ html << form_builder.file_field(@method)
26
+ if image.exists?
27
+ html << form_builder.check_box("destroy_#{@method}")
28
+ html.text! ' Datei löschen'
29
+ end
30
+ return html.target!
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,5 @@
1
+ module Interview
2
+ class IntegerAttribute < Attribute
3
+
4
+ end
5
+ end
@@ -0,0 +1,129 @@
1
+ module Interview
2
+ class Link < Control
3
+ include HasControls
4
+
5
+ attr_accessor :image, :caption, :hint, :style, :active,
6
+ :url, :controller, :object, :action, :http_method, :redirect_to, :nested_resource, :trail
7
+ attr_reader :url_params, :html_class
8
+
9
+ def initialize(params={})
10
+ @html_class = []
11
+ @url_params = {}
12
+ super
13
+ end
14
+
15
+ def scope=(scope)
16
+ @url_params[:scope] = scope
17
+ end
18
+
19
+ def filter=(filter)
20
+ @url_params[:filter] = filter
21
+ end
22
+
23
+ def render
24
+ if @redirect_to
25
+ if @redirect_to == :current
26
+ @url_params[:redirect_to] = h.request.original_url
27
+ elsif @redirect_to == :parent and Object.const_defined? 'Gretel'
28
+ @url_params[:redirect_to] = h.parent_breadcrumb.url
29
+ else
30
+ @url_params[:redirect_to] = @redirect_to
31
+ end
32
+ end
33
+
34
+ if @trail and Object.const_defined? 'Gretel'
35
+ @url_params[:trail] = h.breadcrumb_trail
36
+ end
37
+
38
+ if @url
39
+ url = @url
40
+ elsif @controller
41
+ url_options = @url_option.dup
42
+ opts = {controller: @controller, action: @action}.merge @url_params
43
+ url = h.url_for opts
44
+ else
45
+ url_params = @url_params.dup
46
+ url_params[:action] = @action if @action and not %w(index show destroy).include? @action
47
+ object = @object || find_attribute!(:object)
48
+ url_params.each do |key, value|
49
+ url_params[key] = value.call(self) if value.is_a? Proc
50
+ end
51
+ if @nested_resource and assoc_object
52
+ url = h.polymorphic_path [assoc_object, object], url_params
53
+ else
54
+ url = h.polymorphic_path object, url_params
55
+ end
56
+ end
57
+
58
+ html_options = {}
59
+ html_class = @html_class.dup
60
+ if @action == 'destroy'
61
+ html_options[:method] = :delete
62
+ html_options[:data] = { confirm: 'Are you sure?' }
63
+ end
64
+ if @http_method
65
+ html_options[:method] = @http_method.to_sym
66
+ end
67
+
68
+ if @hint
69
+ html_class << 'action_hint'
70
+ html_options[:'data-toggle'] = 'tooltip'
71
+ html_options[:title] = @hint
72
+ end
73
+
74
+ if @style and respond_to? "render_#{@style}_style", true
75
+ return send "render_#{@style}_style", url, html_class, html_options
76
+ else
77
+ return render_link url, html_class, html_options
78
+ end
79
+ end
80
+
81
+ def object # todo: Überdenken
82
+ find_attribute(:object)
83
+ end
84
+
85
+ def assoc_object # todo: Überdenken
86
+ find_attribute(:assoc_object)
87
+ end
88
+
89
+ protected
90
+
91
+ def render_button_style(url, html_class=[], html_options={})
92
+ html_class << 'btn btn-default'
93
+ return render_link(url, html_class, html_options)
94
+ end
95
+
96
+ def render_primary_button_style(url, html_class=[], html_options={})
97
+ html_class << 'btn btn-primary'
98
+ return render_link(url, html_class, html_options)
99
+ end
100
+
101
+ def render_list_style(url, html_class=[], html_options={})
102
+ html = Builder::XmlMarkup.new
103
+ li_class = @active ? 'active' : ''
104
+ html.li class: li_class do
105
+ html << render_link(url, html_class, html_options)
106
+ end
107
+ return html.target!
108
+ end
109
+
110
+ def render_link(url, html_class=[], html_options={})
111
+ class_string = html_class.join(' ')
112
+ html_options[:class] = class_string unless html_class.empty?
113
+ return h.link_to(url, html_options) do
114
+ html = Builder::XmlMarkup.new
115
+ if @controls.empty?
116
+ html.span '', class: "glyphicon glyphicon-#{@image}" if @image
117
+ html.text! ' ' if @image and @caption
118
+ html << @caption if @caption
119
+ else
120
+ @controls.each do |control|
121
+ html << control.render
122
+ end
123
+ end
124
+ html.target!.html_safe
125
+ end
126
+ end
127
+
128
+ end
129
+ end
@@ -0,0 +1,21 @@
1
+ module Interview
2
+ class List < Control
3
+ include HasControls
4
+
5
+ attr_accessor :objects
6
+ attr_reader :object
7
+
8
+ def render
9
+ objects = @objects || find_attribute!(:objects)
10
+ html = Builder::XmlMarkup.new
11
+ objects.each do |object|
12
+ @object = object
13
+ @controls.each do |control|
14
+ html << control.render
15
+ end
16
+ end
17
+ return html.target!
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,55 @@
1
+ module Interview
2
+ class Navigation < Control
3
+ include HasControls
4
+
5
+ attr_accessor :controller_name, :action_name, :current_scope, :current_filter
6
+
7
+ def render
8
+ auto_set_active
9
+
10
+ html = Builder::XmlMarkup.new
11
+ html.ul class: 'nav nav-pills nav-stacked' do
12
+ @controls.each do |control|
13
+ html << control.render
14
+ end
15
+ end
16
+ return html.target!
17
+ end
18
+
19
+ private
20
+
21
+ def auto_set_active
22
+ siblings.each { |sib| sib.active = false }
23
+ if (nav_item = siblings.find { |sib| controller_match(sib) && action_match(sib) && scope_match(sib) && filter_match(sib) })
24
+ nav_item.active = true
25
+ elsif (nav_item = siblings.find { |sib| controller_match(sib) && scope_match(sib) && filter_match(sib) })
26
+ nav_item.active = true
27
+ elsif (nav_item = siblings.find { |sib| controller_match(sib) && (scope_match(sib) || filter_match(sib)) })
28
+ nav_item.active = true
29
+ elsif (nav_item = siblings.find { |sib| controller_match(sib) })
30
+ nav_item.active = true
31
+ end
32
+ end
33
+
34
+ def controller_match(nav_item)
35
+ return @controller_name == nav_item.controller
36
+ end
37
+
38
+ def action_match(nav_item)
39
+ return @action_name == nav_item.action
40
+ end
41
+
42
+ def scope_match(nav_item)
43
+ return true if @current_scope.nil?
44
+ return false if nav_item.url_options[:scope].nil?
45
+ return true if nav_item.url_options[:scope] == @current_scope
46
+ end
47
+
48
+ def filter_match(nav_item)
49
+ return true if @current_filter.nil?
50
+ return false if nav_item.url_options[:filter].nil?
51
+ return @current_filter.all? { |key, value| nav_item.url_options[:filter][key] == value }
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,26 @@
1
+ module Interview
2
+ class NavigationItem < Link
3
+
4
+ include HasControls
5
+
6
+ attr_accessor :active
7
+
8
+ def render
9
+ css_class = "level#{ancestors.count-1}"
10
+ css_class += " active" if @active
11
+ show_siblings = @active || siblings.any? { |sib| sib.active }
12
+
13
+ html = Builder::XmlMarkup.new
14
+ html.li class: css_class do
15
+ html << super
16
+ end
17
+ if show_siblings
18
+ @controls.each do |c|
19
+ html << c.render
20
+ end
21
+ end
22
+ return html.target!
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,51 @@
1
+ module Interview
2
+ class NestedForm < Control
3
+ include HasControls
4
+
5
+ attr_accessor :polymorphic, :align # todo: align einbauen
6
+ attr_reader :form_builder, :object
7
+
8
+ def render
9
+ assoc_form_builder = find_attribute! :form_builder
10
+ assoc_method = find_attribute! :assoc_method
11
+ objects = find_attribute! :objects
12
+
13
+ html = Builder::XmlMarkup.new
14
+ html.div class: 'nested_forms' do
15
+ html << assoc_form_builder.fields_for(assoc_method.to_sym, objects) do |form_builder|
16
+ if @polymorphic
17
+ render_polymorphic_nested_form(form_builder)
18
+ else
19
+ render_nested_form(form_builder)
20
+ end
21
+ end
22
+ end
23
+ return html.target!
24
+ end
25
+
26
+ def render_nested_form(form_builder)
27
+ @form_builder = form_builder
28
+ @object = form_builder.object
29
+ html = Builder::XmlMarkup.new
30
+ html.div class: 'nested_form collapse in' do
31
+ @controls.each do |control|
32
+ html << control.render
33
+ end
34
+ html << form_builder.hidden_field(:id)
35
+ html << form_builder.hidden_field(:_destroy, class: 'nested_form_destroy')
36
+ end
37
+ html.target!.html_safe
38
+ end
39
+
40
+ def render_polymorphic_nested_form(form_builder)
41
+ object = form_builder.object
42
+ if klass = "#{object.class.name}NestedForm".safe_constantize
43
+ nested_form = klass.new(parent: self)
44
+ return nested_form.render_nested_form(form_builder)
45
+ else
46
+ return self.render_nested_form(form_builder)
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,80 @@
1
+ module Interview
2
+ class NestedFormAddLink < Control
3
+
4
+ attr_accessor :style, :polymorphic_classes
5
+
6
+ def render
7
+ if @style and @style.to_sym == :horizontal_form
8
+ html = Builder::XmlMarkup.new # todo: in eigenes Objekt auslagern?
9
+ html.div class: 'row' do
10
+ html.div class: 'col-xs-9 col-xs-offset-3' do
11
+ html << render_link
12
+ end
13
+ end
14
+ return html.target!
15
+ else
16
+ return render_link
17
+ end
18
+ end
19
+
20
+ def render_link
21
+ form_builder = find_attribute! :form_builder
22
+ assoc_method = find_attribute!(:assoc_method).to_sym
23
+ if @polymorphic_classes
24
+ return render_polymorphic_link(form_builder, assoc_method)
25
+ else
26
+ html = render_form(form_builder, assoc_method)
27
+ text = h.t('views.nested_form_add', association: find_attribute!(:singular_title))
28
+ return h.content_tag :a, text, { href: '#', class: 'nested_form_add_link', data: { content: CGI::escapeHTML(html) } }, false
29
+ end
30
+ end
31
+
32
+ protected
33
+
34
+ def render_polymorphic_link(form_builder, assoc_method)
35
+ poly_classes = @polymorphic_classes.map do |poly_class|
36
+ poly_class.is_a?(String) ? poly_class.camelcase.constantize : poly_class
37
+ end
38
+
39
+ select_options = [[ h.t('helpers.select.prompt'), nil ]]
40
+ select_options += poly_classes.map do |poly_class|
41
+ [ poly_class.model_name.human, poly_class.model_name.singular ]
42
+ end
43
+
44
+ data_content = {}
45
+ poly_classes.each do |poly_class|
46
+ new_object = form_builder.object.association(assoc_method.to_sym).build(type: poly_class.name)
47
+ html = render_form(form_builder, assoc_method, new_object)
48
+ data_content[poly_class.model_name.singular] = html
49
+ end
50
+
51
+ html = Builder::XmlMarkup.new
52
+ html.div do
53
+ html << h.select_tag("add_link_class", h.options_for_select(select_options), class: 'form-control', style: 'display: inline; width: auto;')
54
+ html.text! ' '
55
+ html << h.content_tag(:a, h.t('views.add'), {href: '#', class: 'nested_form_polymorphic_add_link btn btn-default',
56
+ data: { content: CGI::escapeHTML(data_content.to_json) } }, false)
57
+ end
58
+ return html.target!
59
+ end
60
+
61
+ def render_form(form_builder, assoc_method, new_object=nil)
62
+ new_object ||= form_builder.object.association(assoc_method.to_sym).build
63
+ new_object.assign_attributes(new_object.class.defaults)
64
+ if new_object_assoc = new_object.class.reflect_on_all_associations.find { |a|
65
+ a.foreign_key == form_builder.object.association(assoc_method.to_sym).reflection.foreign_key }
66
+ new_object.association(new_object_assoc.name).target ||= form_builder.object
67
+ end
68
+
69
+ nested_form = find_attribute! :nested_form
70
+ return form_builder.fields_for(assoc_method, new_object, :child_index => "new_association") do |builder|
71
+ if @polymorphic_classes
72
+ nested_form.render_polymorphic_nested_form(builder)
73
+ else
74
+ nested_form.render_nested_form(builder)
75
+ end
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,28 @@
1
+ module Interview
2
+ class NestedFormRemoveLink < Control
3
+
4
+ attr_accessor :style
5
+
6
+ def render
7
+ if @style and @style.to_sym == :horizontal_form
8
+ html = Builder::XmlMarkup.new
9
+ html.div class: 'row' do
10
+ html.div class: 'col-xs-9 col-xs-offset-3' do
11
+ html << render_link
12
+ end
13
+ end
14
+ return html.target!
15
+ else
16
+ return render_link
17
+ end
18
+ end
19
+
20
+ def render_link
21
+ assoc_object = find_attribute! :assoc_object
22
+ assoc_method = find_attribute!(:assoc_method).to_s
23
+ text = h.t('views.nested_form_remove', association: assoc_object.class.human_attribute_name(assoc_method.singularize)) # todo: in view auslagern
24
+ return h.content_tag :a, text, href: '#', class: 'nested_form_remove_link'
25
+ end
26
+
27
+ end
28
+ end