freeform 0.0.3.rc1 → 0.0.3.rc2

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.
data/README.md CHANGED
@@ -12,7 +12,7 @@ FreeForm is designed primarily with Rails in mind, but it should work on any Rub
12
12
 
13
13
  Add this line to your application's Gemfile:
14
14
 
15
- gem 'freeform'
15
+ gem 'freeform', '~> 0.0.3rc2'
16
16
 
17
17
  And then execute:
18
18
 
@@ -212,16 +212,28 @@ form.build_phone_numbers(:phone => Phone.new)
212
212
  form.build_phone_number(:phone => Phone.new)
213
213
  ```
214
214
 
215
- You can specify the default initializers for that form with the accessor `#{nested_form_name}_form_initializer`.
215
+ **Working with nested_form gem**
216
+ In order to support the `nested_form` gem, FreeForm currently uses a bit of hackiness. You actually need to specify an option on your nested forms called `class_initializer`, that points to a class method to use to specify the default parameters. You can either provide the method hardcoded into the class, or set it externally. It accepts either a hardcoded hash, or a Proc.
216
217
  ```ruby
217
- form = UserForm.new(
218
- :user => User.new,
219
- :phone_numbers_form_initializer => {:phone => Phone.new} )
218
+ class UserForm < FreeForm::Form
219
+ form_models :user
220
220
 
221
- form.build_phone_numbers
222
- form.build_phone_number
221
+ property :username, :on => :user
222
+ property :email, :on => :user
223
+
224
+ nested_form :phone_numbers, :class_initializer => :phone_initializer do
225
+ form_models :phone
226
+
227
+ property :area_code, :on => :phone
228
+ property :number, :on => :phone
229
+ end
230
+ end
231
+
232
+ UserForm.phone_initializer = lambda { { :phone => Phone.new } }
233
+ form = UserForm.new( :user => User.new )
234
+ form.build_phone_number # Uses Phone.new to initialize the nested form.
223
235
  ```
224
- This is a necessary parameter if you're using the `nested_form` gem, as new nested forms are initialized automatically.
236
+ I apologize for the ugliness - In the future, I plan to roll FreeForm's own version of the `nested_form` javascript functionality.
225
237
 
226
238
  ## Initialize With Care!
227
239
 
@@ -238,7 +250,7 @@ class UserForm < FreeForm::Form
238
250
  property :username, :on => :user
239
251
  property :email, :on => :user
240
252
 
241
- nested_form :phone_numbers do
253
+ nested_form :phone_numbers, :class_initializer => :phone_initializer do
242
254
  form_models :phone
243
255
 
244
256
  property :area_code, :on => :phone
@@ -253,6 +265,7 @@ Will the current_user's phone numbers automatically appear as nested forms? **No
253
265
  If you want them there, put them there, like this:
254
266
 
255
267
  ```ruby
268
+ UserForm.phone_initializer = lambda { { :phone => current_user.phone_numbers.build } }
256
269
  current_user.phone_numbers.each do |phone_number|
257
270
  form.build_phone_number(:phone => phone_number)
258
271
  end
@@ -12,6 +12,21 @@ module FreeForm
12
12
  attr_accessor :nested_forms
13
13
 
14
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
29
+
15
30
  # Define an attr_accessor for the parent class to hold this attribute
16
31
  declared_model(attribute)
17
32
 
@@ -19,6 +34,22 @@ module FreeForm
19
34
  nested_form_class = Class.new(FreeForm::Form) do
20
35
  include FreeForm::Property
21
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
22
53
  end
23
54
  self.const_set("#{attribute.to_s.camelize}Form", nested_form_class)
24
55
 
@@ -53,18 +84,10 @@ module FreeForm
53
84
  @nested_attributes ||= []
54
85
  end
55
86
 
56
- # Example: form.address_form_initializer (aliased to form.addresses_form_initializer)
57
- attr_accessor :"#{attribute}_form_initializer"
58
- alias_method :"#{singularized_attribute}_form_initializer", :"#{attribute}_form_initializer"
59
- alias_method :"#{singularized_attribute}_form_initializer=", :"#{attribute}_form_initializer="
60
-
61
87
  # Example: form.build_addresses (optional custom initializer)
62
- define_method(:"build_#{attribute}") do |initializer=nil|
88
+ define_method(:"build_#{attribute}") do |initializer={}|
63
89
  # Get correct class
64
90
  form_class = self.class.nested_forms[:"#{attribute}"]
65
-
66
- # Set default intializer if none provided
67
- initializer ||= send("#{attribute}_form_initializer").call
68
91
 
69
92
  # Build new model
70
93
  form_model = form_class.new(initializer)
@@ -93,4 +93,7 @@ module FreeForm
93
93
  end
94
94
  end
95
95
  end
96
+
97
+ #Instance Methods
98
+ #----------------------------------------------------------------------------
96
99
  end
@@ -1,3 +1,3 @@
1
1
  module Freeform
2
- VERSION = "0.0.3.rc1"
2
+ VERSION = "0.0.3.rc2"
3
3
  end
@@ -57,12 +57,12 @@ describe FreeForm::Form do
57
57
  allow_destroy_on_save
58
58
 
59
59
  property :username, :on => :user
60
- property :email, :on => :user
60
+ property :email, :on => :user
61
61
  property :street, :on => :address
62
62
  property :city, :on => :address
63
63
  property :state, :on => :address
64
64
 
65
- has_many :phone_numbers do
65
+ has_many :phone_numbers, :class_initializer => :phone_number_initializer do
66
66
  form_model :phone
67
67
  validate_models
68
68
  allow_destroy_on_save
@@ -79,11 +79,8 @@ describe FreeForm::Form do
79
79
  end
80
80
 
81
81
  let(:form) do
82
- form_model = form_class.new(
83
- :user => user_class.new,
84
- :address => address_class.new,
85
- :phone_numbers_form_initializer => lambda { { :phone => phone_class.new } }
86
- )
82
+ form_class.phone_number_initializer = lambda { {:phone => phone_class.new} }
83
+ form_model = form_class.new( :user => user_class.new, :address => address_class.new)
87
84
  form_model.build_phone_number
88
85
  form_model
89
86
  end
@@ -9,13 +9,13 @@ describe FreeForm::Nested do
9
9
  klass = Class.new(Module) do
10
10
  include FreeForm::Property
11
11
  include FreeForm::Nested
12
-
13
- has_many :mailing_addresses do
12
+
13
+ has_many :mailing_addresses, :class_initializer => :mailing_address_initializer do
14
14
  declared_model :address
15
15
 
16
- property :street, :on => :address
16
+ property :street, :on => :address
17
17
  end
18
-
18
+
19
19
  def initialize(h={})
20
20
  h.each {|k,v| send("#{k}=",v)}
21
21
  end
@@ -28,9 +28,8 @@ describe FreeForm::Nested do
28
28
  end
29
29
 
30
30
  let(:form) do
31
- form_model = form_class.new(
32
- :mailing_address_form_initializer => lambda { { :address => OpenStruct.new } }
33
- )
31
+ form_class.mailing_address_initializer = lambda { { :address => OpenStruct.new } }
32
+ form_model = form_class.new
34
33
  end
35
34
 
36
35
  describe "form class" do
@@ -53,7 +52,8 @@ describe FreeForm::Nested do
53
52
 
54
53
  it "builds unique models" do
55
54
  # Using module here, since they initialize uniquely
56
- form.mailing_address_form_initializer = lambda { { :address => Module.new } }
55
+ form_class.mailing_address_initializer = lambda { { :address => Module.new } }
56
+ form = form_class.new
57
57
  form.build_mailing_address
58
58
  form.build_mailing_address
59
59
  address_1 = form.mailing_addresses.first.address
@@ -61,6 +61,12 @@ describe FreeForm::Nested do
61
61
  address_1.should_not eq(address_2)
62
62
  end
63
63
 
64
+ it "builds initialized models through reflection on association" do
65
+ form_class.mailing_address_initializer = lambda { { :address => Module.new } }
66
+ klass = form_class.reflect_on_association(:mailing_addresses).klass
67
+ klass.new.address.should be_a(Module)
68
+ end
69
+
64
70
  it "allows nested_forms to be built with custom initializers" do
65
71
  form.build_mailing_address(:address => OpenStruct.new(:street => "1600 Pennsylvania Ave."))
66
72
  form.mailing_addresses.first.street.should eq("1600 Pennsylvania Ave.")
@@ -46,12 +46,16 @@ describe FreeForm::Validation do
46
46
  property :username, :on => :user
47
47
  validates :username, :presence => true
48
48
 
49
- nested_form :addresses do
49
+ nested_form :addresses, :class_initializer => :address_initializer do
50
50
  declared_model :address
51
51
 
52
52
  property :street, :on => :address
53
53
  end
54
54
 
55
+ def self.address_initializer
56
+ {:address => OpenStruct.new}
57
+ end
58
+
55
59
  def initialize(h={})
56
60
  h.each {|k,v| send("#{k}=",v)}
57
61
  end
@@ -64,10 +68,8 @@ describe FreeForm::Validation do
64
68
  end
65
69
 
66
70
  let(:form) do
67
- test_form = form_class.new(
68
- :user => user,
69
- :address_form_initializer => lambda { { :address => address } } )
70
- test_form.build_address
71
+ test_form = form_class.new(:user => user)
72
+ test_form.build_address(:address => address)
71
73
  test_form
72
74
  end
73
75
 
@@ -100,7 +102,7 @@ describe FreeForm::Validation do
100
102
  property :form_property
101
103
  validates :form_property, :presence => true
102
104
 
103
- nested_form :addresses do
105
+ nested_form :addresses, :class_initializer => :address_initializer do
104
106
  include ActiveModel::Validations
105
107
  include FreeForm::Property
106
108
  include FreeForm::Nested
@@ -112,6 +114,10 @@ describe FreeForm::Validation do
112
114
  property :city, :on => :address
113
115
  end
114
116
 
117
+ def self.address_initializer
118
+ {:address => OpenStruct.new}
119
+ end
120
+
115
121
  def initialize(h={})
116
122
  h.each {|k,v| send("#{k}=",v)}
117
123
  end
@@ -124,10 +130,8 @@ describe FreeForm::Validation do
124
130
  end
125
131
 
126
132
  let(:form) do
127
- test_form = form_class.new(
128
- :user => user,
129
- :address_form_initializer => lambda { { :address => address } } )
130
- test_form.build_address
133
+ test_form = form_class.new( :user => user )
134
+ test_form.build_address( :address => address )
131
135
  test_form
132
136
  end
133
137
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: freeform
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.rc1
4
+ version: 0.0.3.rc2
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors: