freeform 0.0.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (129) hide show
  1. data/.gitignore +8 -17
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +150 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +31 -43
  6. data/Rakefile +32 -1
  7. data/freeform.gemspec +22 -15
  8. data/lib/freeform/builder/builder_mixin.rb +111 -0
  9. data/lib/freeform/builder/builders.rb +32 -0
  10. data/lib/freeform/builder/engine.rb +14 -0
  11. data/lib/freeform/builder/view_helper.rb +56 -0
  12. data/lib/freeform/form/form_input_key.rb +1 -1
  13. data/lib/freeform/form/nested.rb +17 -55
  14. data/lib/freeform/form/property.rb +82 -42
  15. data/lib/freeform/form/validation.rb +38 -11
  16. data/lib/freeform/form.rb +24 -27
  17. data/lib/freeform/version.rb +1 -1
  18. data/lib/freeform.rb +4 -0
  19. data/lib/generators/freeform/install_generator.rb +17 -0
  20. data/lib/tasks/freeform_tasks.rake +4 -0
  21. data/spec/acceptance_spec.rb +261 -155
  22. data/spec/builder/builder_spec.rb +215 -0
  23. data/spec/builder/view_helper_spec.rb +97 -0
  24. data/spec/dummy/README.rdoc +28 -0
  25. data/spec/dummy/Rakefile +6 -0
  26. data/spec/dummy/app/assets/images/.keep +0 -0
  27. data/spec/dummy/app/assets/javascripts/application.js +5 -0
  28. data/spec/dummy/app/assets/javascripts/jquery.js +9404 -0
  29. data/spec/dummy/app/assets/javascripts/jquery_events_test.js +19 -0
  30. data/spec/dummy/app/assets/javascripts/projects.js +2 -0
  31. data/spec/dummy/app/assets/javascripts/prototype.js +6082 -0
  32. data/spec/dummy/app/assets/javascripts/prototype_events_test.js +20 -0
  33. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  34. data/spec/dummy/app/assets/stylesheets/companies.css +4 -0
  35. data/spec/dummy/app/assets/stylesheets/projects.css +4 -0
  36. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  37. data/spec/dummy/app/controllers/companies_controller.rb +5 -0
  38. data/spec/dummy/app/controllers/projects_controller.rb +11 -0
  39. data/spec/dummy/app/forms/milestone_form.rb +4 -0
  40. data/spec/dummy/app/forms/project_form.rb +11 -0
  41. data/spec/dummy/app/forms/task_form.rb +10 -0
  42. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  43. data/spec/dummy/app/mailers/.keep +0 -0
  44. data/spec/dummy/app/models/.keep +0 -0
  45. data/spec/dummy/app/models/company.rb +5 -0
  46. data/spec/dummy/app/models/milestone.rb +6 -0
  47. data/spec/dummy/app/models/project.rb +9 -0
  48. data/spec/dummy/app/models/project_task.rb +3 -0
  49. data/spec/dummy/app/models/task.rb +7 -0
  50. data/spec/dummy/app/views/companies/new.html.erb +16 -0
  51. data/spec/dummy/app/views/layouts/application.html.erb +19 -0
  52. data/spec/dummy/app/views/projects/new.html.erb +13 -0
  53. data/spec/dummy/app/views/projects/without_intermediate_inputs.html.erb +11 -0
  54. data/spec/dummy/bin/bundle +3 -0
  55. data/spec/dummy/bin/rails +4 -0
  56. data/spec/dummy/bin/rake +4 -0
  57. data/spec/dummy/config/application.rb +35 -0
  58. data/spec/dummy/config/boot.rb +5 -0
  59. data/spec/dummy/config/database.yml +25 -0
  60. data/spec/dummy/config/environment.rb +5 -0
  61. data/spec/dummy/config/environments/development.rb +29 -0
  62. data/spec/dummy/config/environments/production.rb +80 -0
  63. data/spec/dummy/config/environments/test.rb +36 -0
  64. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  65. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  66. data/spec/dummy/config/initializers/inflections.rb +16 -0
  67. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  68. data/spec/dummy/config/initializers/secret_token.rb +13 -0
  69. data/spec/dummy/config/initializers/session_store.rb +3 -0
  70. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  71. data/spec/dummy/config/locales/en.yml +23 -0
  72. data/spec/dummy/config/routes.rb +5 -0
  73. data/spec/dummy/config.ru +4 -0
  74. data/spec/dummy/db/migrate/20110710143903_initial_tables.rb +38 -0
  75. data/spec/dummy/db/schema.rb +43 -0
  76. data/spec/dummy/db/test.sqlite3 +0 -0
  77. data/spec/dummy/lib/assets/.keep +0 -0
  78. data/spec/dummy/log/.keep +0 -0
  79. data/spec/dummy/log/development.log +0 -0
  80. data/spec/dummy/log/test.log +39736 -0
  81. data/spec/dummy/public/404.html +58 -0
  82. data/spec/dummy/public/422.html +58 -0
  83. data/spec/dummy/public/500.html +57 -0
  84. data/spec/dummy/public/favicon.ico +0 -0
  85. data/spec/dummy/tmp/cache/assets/C54/850/sprockets%2Fd484f47085686f151320ff7248bb5105 +0 -0
  86. data/spec/dummy/tmp/cache/assets/C76/160/sprockets%2F49c594d143212b346d11f1ecf9358103 +0 -0
  87. data/spec/dummy/tmp/cache/assets/C99/4D0/sprockets%2F5e30a6b911437f1428dc32c3ae182123 +0 -0
  88. data/spec/dummy/tmp/cache/assets/C99/7D0/sprockets%2F79513e6956e0ee8624976e041fd5636d +0 -0
  89. data/spec/dummy/tmp/cache/assets/CAA/C90/sprockets%2F1e6c8ee1258009385ccf5b84015424b3 +0 -0
  90. data/spec/dummy/tmp/cache/assets/CB2/CB0/sprockets%2F11cc8d161d71a716dd36f16849d90870 +0 -0
  91. data/spec/dummy/tmp/cache/assets/CB7/7F0/sprockets%2Fac97b043470f6fcc925c352f16956643 +0 -0
  92. data/spec/dummy/tmp/cache/assets/CBA/680/sprockets%2F912d84e091e5f2190b1ab7926de19679 +0 -0
  93. data/spec/dummy/tmp/cache/assets/CC7/430/sprockets%2F48e99a3e16ba3e65749e009d82546f94 +0 -0
  94. data/spec/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  95. data/spec/dummy/tmp/cache/assets/CDB/8A0/sprockets%2Faed2a2575c376263c26e93b56b57051d +0 -0
  96. data/spec/dummy/tmp/cache/assets/CF1/E80/sprockets%2F7735295e1e3085f2e1dc29d59a45e8e6 +0 -0
  97. data/spec/dummy/tmp/cache/assets/D0F/E60/sprockets%2F1123d9a479fdf5c2b8415087e2a43ec6 +0 -0
  98. data/spec/dummy/tmp/cache/assets/D1F/A10/sprockets%2F60317e62cb324bfd9987e8da9636fd06 +0 -0
  99. data/spec/dummy/tmp/cache/assets/D25/E20/sprockets%2F29ba1a4a2b611731334f54abb9e5b5d1 +0 -0
  100. data/spec/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  101. data/spec/dummy/tmp/cache/assets/D35/760/sprockets%2F49e26620c5c743ac4cdab7703f54db06 +0 -0
  102. data/spec/dummy/tmp/cache/assets/D49/870/sprockets%2F90896142645585acc8baf56ad57e3afb +0 -0
  103. data/spec/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  104. data/spec/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  105. data/spec/dummy/tmp/cache/assets/D62/F00/sprockets%2F6ac03a007f26b1c18ed3d53498ad3eb8 +0 -0
  106. data/spec/dummy/tmp/cache/assets/D79/BC0/sprockets%2F85a1db977361cc5130fcefb4637ff67e +0 -0
  107. data/spec/dummy/tmp/cache/assets/D87/1F0/sprockets%2F61c9ceafb877fb740c67416ff6f782a9 +0 -0
  108. data/spec/dummy/tmp/cache/assets/DA8/900/sprockets%2Fde7a2b3987b89b9d9afb268ce4204a4a +0 -0
  109. data/spec/dummy/tmp/cache/assets/DAD/4F0/sprockets%2F765acd1bf68dc90f7d3e61da78b1e659 +0 -0
  110. data/spec/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  111. data/spec/dummy/tmp/cache/assets/E03/3F0/sprockets%2F82b37ae9eccec44c1ef44cfdd07d8534 +0 -0
  112. data/spec/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  113. data/spec/dummy/tmp/cache/assets/E0A/CA0/sprockets%2F7fe72ac1c0db1a7e8e7f59cf25e8a39e +0 -0
  114. data/spec/dummy/tmp/cache/assets/E20/9B0/sprockets%2F2fa6cd86b1af7bda41f5b7921cdadf10 +0 -0
  115. data/spec/dummy/tmp/cache/assets/E3A/A60/sprockets%2F7c72c96cfc66454caf5fc8ca0fedd4f3 +0 -0
  116. data/spec/dummy/tmp/cache/assets/E54/400/sprockets%2Fd0cbc16cc37efcf9dc41f242b5dbbf81 +0 -0
  117. data/spec/dummy/tmp/cache/assets/EB7/AB0/sprockets%2F801d29a5debdbfbfb4eef14d70d9bcdb +0 -0
  118. data/spec/dummy/tmp/cache/assets/F48/5E0/sprockets%2F26cd6ffcffbebbe2fd6cd1a8f0c2debc +0 -0
  119. data/spec/form/nested_spec.rb +75 -61
  120. data/spec/form/property_spec.rb +167 -14
  121. data/spec/form/validation_spec.rb +46 -23
  122. data/spec/javascript_spec.rb +60 -0
  123. data/spec/persistence_spec.rb +608 -0
  124. data/spec/spec_helper.rb +18 -2
  125. data/vendor/assets/javascripts/jquery_freeform.js +120 -0
  126. data/vendor/assets/javascripts/jquery_nested_form.js +0 -0
  127. data/vendor/assets/javascripts/prototype_freeform.js +69 -0
  128. data/vendor/assets/javascripts/prototype_nested_form.js +0 -0
  129. metadata +341 -3
@@ -1,5 +1,3 @@
1
- require 'freeform/form/property'
2
-
3
1
  module FreeForm
4
2
  module Nested
5
3
  def self.included(base)
@@ -9,55 +7,18 @@ module FreeForm
9
7
  module ClassMethods
10
8
  # Nested Forms
11
9
  #------------------------------------------------------------------------
12
- attr_accessor :nested_forms
10
+ attr_accessor :nested_forms
13
11
 
14
- def nested_form(attribute, options={}, &block)
15
- # Specify the class method on which we're defining the initializer for this form.
16
- parent_class = self
17
- initializer_method = options[:class_initializer]
18
- unless initializer_method.nil?
19
- define_singleton_method(:"#{initializer_method}") do
20
- var = instance_variable_get(:"@#{initializer_method}")
21
- var ||= {}
22
- var
23
- end
24
-
25
- define_singleton_method(:"#{initializer_method}=") do |val|
26
- instance_variable_set(:"@#{initializer_method}", val)
27
- end
28
- end
12
+ def nested_form(attribute, options={})
13
+ nested_form_class = options[:class]
14
+ @nested_forms ||= {}
15
+ @nested_forms.merge!({:"#{attribute}" => nested_form_class})
29
16
 
30
17
  # Define an attr_accessor for the parent class to hold this attribute
31
18
  declared_model(attribute)
32
19
 
33
- # Define the new class, and set it up with a new name
34
- nested_form_class = Class.new(FreeForm::Form) do
35
- include FreeForm::Property
36
- self.instance_eval(&block)
37
-
38
- define_singleton_method(:default_initializer) do
39
- unless initializer_method.nil?
40
- method = parent_class.send(initializer_method)
41
- if method.is_a? Proc
42
- method.call
43
- else
44
- method
45
- end
46
- end
47
- end
48
-
49
- def initialize(p={}, *args)
50
- p = self.class.default_initializer.merge(p)
51
- super(p, *args)
52
- end
53
- end
54
- self.const_set("#{attribute.to_s.camelize}Form", nested_form_class)
55
-
56
- @nested_forms ||= {}
57
- @nested_forms.merge!({:"#{attribute}" => nested_form_class})
58
-
59
20
  # Defined other methods
60
- define_nested_model_methods(attribute, nested_form_class)
21
+ define_nested_model_methods(attribute, nested_form_class, options)
61
22
 
62
23
  # Setup Handling for nested attributes
63
24
  define_nested_attribute_methods(attribute, nested_form_class)
@@ -65,18 +26,10 @@ module FreeForm
65
26
  alias_method :has_many, :nested_form
66
27
  alias_method :has_one, :nested_form
67
28
 
68
- # Supporting Methods
69
- #------------------------------------------------------------------------
70
- def reflect_on_association(key, *args)
71
- reflection = OpenStruct.new
72
- reflection.klass = self.nested_forms[key]
73
- reflection
74
- end
75
-
76
29
  protected
77
30
  # Defining Helper Methods For Models
78
31
  #------------------------------------------------------------------------
79
- def define_nested_model_methods(attribute, form_class)
32
+ def define_nested_model_methods(attribute, form_class, options={})
80
33
  singularized_attribute = attribute.to_s.singularize.to_s
81
34
 
82
35
  # Example: form.addresses will return all nested address forms
@@ -85,9 +38,18 @@ module FreeForm
85
38
  end
86
39
 
87
40
  # Example: form.build_addresses (optional custom initializer)
88
- define_method(:"build_#{attribute}") do |initializer={}|
41
+ define_method(:"build_#{attribute}") do |initializer=nil|
42
+ # Builder object
43
+ parent_object = self
44
+
89
45
  # Get correct class
90
46
  form_class = self.class.nested_forms[:"#{attribute}"]
47
+
48
+ # Default Initializer
49
+ if options[:default_initializer]
50
+ initializer ||= instance_eval(&options[:default_initializer])
51
+ end
52
+ initializer ||= {}
91
53
 
92
54
  # Build new model
93
55
  form_model = form_class.new(initializer)
@@ -13,6 +13,10 @@ module FreeForm
13
13
  @models ||= []
14
14
  end
15
15
 
16
+ def child_models
17
+ @child_models ||= []
18
+ end
19
+
16
20
  def declared_model(name, opts={})
17
21
  @models ||= []
18
22
  @models << name
@@ -27,73 +31,109 @@ module FreeForm
27
31
  end
28
32
  alias_method :form_models, :declared_models
29
33
 
34
+ def child_model(name, opts={}, &block)
35
+ @models ||= []
36
+ @models << name
37
+ @child_models ||= []
38
+ @child_models << name
39
+ attr_accessor name
40
+ define_method("initialize_#{name}") do
41
+ instance_variable_set("@#{name}", instance_eval(&block))
42
+ end
43
+ end
44
+
30
45
  # Properties
31
46
  #------------------------------------------------------------------------
32
- def ignored_blank_params
33
- @ignored_blank_params ||= []
47
+ def property_mappings
48
+ # Take the form of {:property => {:model => model, :field => field, :ignore_blank => false}}
49
+ @property_mappings ||= Hash.new
34
50
  end
35
51
 
36
52
  def allow_destroy_on_save
37
53
  # Define _destroy method for marked-for-destruction handling
38
54
  attr_accessor :_destroy
39
- alias_method :marked_for_destruction, :_destroy
55
+ define_method(:_destroy=) do |value|
56
+ false_values = [nil, 0 , false, "0", "false"]
57
+ @_destroy = !(false_values.include?(value))
58
+ end
59
+ alias_method :marked_for_destruction?, :_destroy
60
+ define_method(:mark_for_destruction) do
61
+ @_destroy = true
62
+ end
40
63
  end
41
64
 
42
65
  def property(attribute, options={})
43
- if options[:on]
44
- def_delegator options[:on], attribute
45
- def_delegator options[:on], "#{attribute}=".to_sym
46
- else
66
+ @property_mappings ||= Hash.new
67
+ model = options[:on] ? options [:on] : :self
68
+ field = options[:as] ? options[:as] : attribute.to_sym
69
+ ignore_blank = options[:ignore_blank] ? options[:ignore_blank] : false
70
+ @property_mappings.merge!({field => {:model => model, :field => attribute.to_sym, :ignore_blank => ignore_blank}})
71
+
72
+ if model == :self
47
73
  attr_accessor attribute
74
+ else
75
+ define_method("#{field}") do
76
+ send("#{model}").send("#{attribute}")
77
+ end
78
+
79
+ define_method("#{field}=") do |value|
80
+ send("#{model}").send("#{attribute}=", value)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ attr_accessor :parent_form
87
+
88
+ class DateParamsFilter
89
+ def call(params)
90
+ date_attributes = {}
91
+
92
+ params.each do |attribute, value|
93
+ if value.is_a?(Hash)
94
+ call(value) # TODO: #validate should only handle local form params.
95
+ elsif matches = attribute.match(/^(\w+)\(.i\)$/)
96
+ date_attribute = matches[1]
97
+ date_attributes[date_attribute] = params_to_date(
98
+ params.delete("#{date_attribute}(1i)"),
99
+ params.delete("#{date_attribute}(2i)"),
100
+ params.delete("#{date_attribute}(3i)")
101
+ )
102
+ end
103
+ end
104
+ params.merge!(date_attributes)
105
+ end
106
+
107
+ private
108
+ def params_to_date(year, month, day)
109
+ day ||= 1 # FIXME: is that really what we want? test.
110
+ begin # TODO: test fails.
111
+ return Date.new(year.to_i, month.to_i, day.to_i)
112
+ rescue ArgumentError => e
113
+ return nil
48
114
  end
49
- @ignored_blank_params ||= []
50
- @ignored_blank_params << attribute if options[:ignore_blank]
51
115
  end
52
116
  end
53
117
 
54
118
  def assign_params(params)
55
- filter_dates(params)
119
+ DateParamsFilter.new.call(params)
56
120
  params.each_pair do |attribute, value|
57
- self.send :"#{attribute}=", value unless ignore?(attribute, value)
121
+ assign_attribute(attribute, value)
58
122
  end
59
123
  self
60
124
  end
61
125
  alias_method :assign_attributes, :assign_params
62
126
  alias_method :populate, :assign_params
63
127
  alias_method :fill, :assign_params
64
-
65
- def ignore?(attribute, value)
66
- ignored_if_blank = self.class.ignored_blank_params
67
- return (ignored_if_blank.include?(attribute.to_sym) && value.blank?)
68
- end
69
128
 
70
- private
71
- #TODO: This should be its own model
72
- def filter_dates(params)
73
- date_attributes = {}
74
- params.each do |attribute, value|
75
- if attribute.to_s.include?("(1i)") || attribute.to_s.include?("(2i)") || attribute.to_s.include?("(3i)")
76
- date_attribute = attribute.to_s.gsub(/(\(.*\))/, "")
77
- date_attributes[date_attribute.to_sym] = params_to_date(
78
- params.delete("#{date_attribute}(1i)"),
79
- params.delete("#{date_attribute}(2i)"),
80
- params.delete("#{date_attribute}(3i)")
81
- )
82
- end
83
- end
84
- params.merge!(date_attributes)
129
+ private
130
+ def assign_attribute(attribute, value)
131
+ self.send :"#{attribute}=", value unless ignore?(attribute, value)
85
132
  end
86
-
87
- def params_to_date(year, month, day)
88
- day ||= 1
89
- begin
90
- return Date.new(year.to_i, month.to_i, day.to_i)
91
- rescue => e
92
- return nil
93
- end
133
+
134
+ def ignore?(attribute, value)
135
+ mapping = self.class.property_mappings[attribute.to_sym]
136
+ return (mapping[:ignore_blank] && value.blank?) unless mapping.nil?
94
137
  end
95
138
  end
96
-
97
- #Instance Methods
98
- #----------------------------------------------------------------------------
99
139
  end
@@ -2,6 +2,7 @@ module FreeForm
2
2
  module Validation
3
3
  def self.included(base)
4
4
  base.extend(ClassMethods)
5
+ extend FreeForm::Property
5
6
  end
6
7
 
7
8
  module ClassMethods
@@ -10,25 +11,51 @@ module FreeForm
10
11
  end
11
12
  end
12
13
 
13
- protected
14
+ protected
14
15
  def model_validity
15
- model_validity = true
16
- self.class.models.each do |form_model|
16
+ self.class.models.each do |form_model|
17
17
  if send(form_model).is_a?(Array)
18
- send(form_model).each { |model| model_validity = validate_and_append_errors(model) && model_validity }
18
+ # If it's an array, we're dealing with nested forms
19
+ errors.add(:base, "has invalid nested forms") unless validate_nested_forms(send(form_model))
19
20
  else
20
- model_validity = validate_and_append_errors(send(form_model)) && model_validity
21
+ # Otherwise, validate the form object
22
+ validate_form_model(form_model)
21
23
  end
22
24
  end
23
- return model_validity
24
25
  end
25
26
 
26
- def validate_and_append_errors(model)
27
- unless model.valid?
28
- model.errors.each { |error, message| self.errors.add(error, message) }
29
- return false
27
+ private
28
+ def validate_nested_forms(form_array)
29
+ form_validity = true
30
+ form_array.each do |model|
31
+ form_validity = false unless model.valid?
30
32
  end
31
- return true
33
+ form_validity
34
+ end
35
+
36
+ def validate_form_model(form_model)
37
+ model = send(form_model)
38
+ append_errors(form_model)
39
+ return model.valid?
40
+ end
41
+
42
+ def append_errors(form_model)
43
+ model = send(form_model)
44
+ model.valid?
45
+ model.errors.each do |error, message|
46
+ if find_form_field_from_model_field(form_model, error)
47
+ self.errors.add(find_form_field_from_model_field(form_model, error), message)
48
+ end
49
+ end
50
+ end
51
+
52
+ def find_form_field_from_model_field(model, field)
53
+ self.class.property_mappings.each_pair do |property, attributes|
54
+ if (attributes[:model] == model.to_sym) && (attributes[:field] == field.to_sym)
55
+ return property
56
+ end
57
+ end
58
+ return false
32
59
  end
33
60
  end
34
61
  end
data/lib/freeform/form.rb CHANGED
@@ -22,51 +22,48 @@ module FreeForm
22
22
  # Instance Methods
23
23
  #----------------------------------------------------------------------------
24
24
  # Required for ActiveModel
25
- def persisted?
26
- false
27
- end
25
+ def persisted?; false end
28
26
 
29
27
  def initialize(h={})
30
28
  h.each {|k,v| send("#{k}=",v)}
29
+ initialize_child_models
31
30
  end
32
31
 
33
32
  def save
34
33
  return false unless valid?
34
+
35
35
  self.class.models.each do |form_model|
36
- if send(form_model).is_a?(Array)
37
- send(form_model).each { |model| return model.save }
38
- else
39
- if marked_for_destruction?
40
- send(form_model).destroy
41
- else
42
- return false unless send(form_model).save
43
- end
44
- end
36
+ model = send(form_model)
37
+ model.is_a?(Array) ? model.each { |m| m.save } : save_or_destroy(model)
45
38
  end
46
- return true
47
39
  end
48
40
 
49
41
  def save!
50
42
  raise FreeForm::FormInvalid, "form invalid." unless valid?
43
+
51
44
  self.class.models.each do |form_model|
52
- if send(form_model).is_a?(Array)
53
- send(form_model).each { |model| model.save! }
54
- else
55
- if marked_for_destruction?
56
- send(form_model).destroy
57
- else
58
- send(form_model).save!
59
- end
60
- end
45
+ model = send(form_model)
46
+ model.is_a?(Array) ? model.each { |m| m.save! } : save_or_destroy!(model)
61
47
  end
62
48
  end
63
49
 
50
+ private
51
+ def initialize_child_models
52
+ self.class.child_models.each do |c|
53
+ send("initialize_#{c}")
54
+ end
55
+ end
56
+
57
+ def save_or_destroy(model)
58
+ marked_for_destruction? ? model.destroy : model.save
59
+ end
60
+
61
+ def save_or_destroy!(model)
62
+ marked_for_destruction? ? model.destroy : model.save!
63
+ end
64
+
64
65
  def marked_for_destruction?
65
- if self.respond_to?(:_destroy)
66
- return self._destroy
67
- else
68
- return false
69
- end
66
+ respond_to?(:_destroy) ? _destroy : false
70
67
  end
71
68
  end
72
69
  end
@@ -1,3 +1,3 @@
1
1
  module Freeform
2
- VERSION = "0.0.4"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/freeform.rb CHANGED
@@ -2,4 +2,8 @@ require 'freeform/version'
2
2
  require 'freeform/form'
3
3
 
4
4
  if defined?(Rails) # Where to include Rails specific modules...
5
+ require 'freeform/builder/builder_mixin'
6
+ require 'freeform/builder/builders'
7
+ require 'freeform/builder/view_helper'
8
+ require 'freeform/builder/engine'
5
9
  end
@@ -0,0 +1,17 @@
1
+ module FreeForm
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+ def self.source_root
5
+ File.expand_path('../../../../vendor/assets/javascripts', __FILE__)
6
+ end
7
+
8
+ def copy_jquery_file
9
+ if File.exists?('public/javascripts/prototype.js')
10
+ copy_file 'prototype_freeform.js', 'public/javascripts/freeform.js'
11
+ else
12
+ copy_file 'jquery_freeform.js', 'public/javascripts/freeform.js'
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :freeform do
3
+ # # Task goes here
4
+ # end