reform 1.0.4 → 1.1.0

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.
@@ -1,65 +1,81 @@
1
1
  require 'test_helper'
2
+ require 'reform/active_record'
3
+
4
+ # ActiveRecord::Schema.define do
5
+ # create_table :artists do |table|
6
+ # table.column :name, :string
7
+ # table.timestamps
8
+ # end
9
+ # create_table :songs do |table|
10
+ # table.column :title, :string
11
+ # table.column :artist_id, :integer
12
+ # table.column :album_id, :integer
13
+ # table.timestamps
14
+ # end
15
+ # create_table :albums do |table|
16
+ # table.column :title, :string
17
+ # table.timestamps
18
+ # end
19
+ # end
20
+ # Artist.new(:name => "Racer X").save
21
+
2
22
 
3
23
  class ActiveRecordTest < MiniTest::Spec
4
- let (:form) do
5
- require 'reform/active_record'
6
- Class.new(Reform::Form) do
7
- include Reform::Form::ActiveRecord
8
- model :artist
24
+ class SongForm < Reform::Form
25
+ include Reform::Form::ActiveRecord
26
+ model :song
9
27
 
10
- property :name
11
- property :created_at
28
+ property :title
29
+ property :created_at
12
30
 
13
- validates_uniqueness_of :name
14
- validates :created_at, :presence => true # have another property to test if we mix up.
15
- end.
16
- new(Artist.new)
31
+ validates_uniqueness_of :title
32
+ validates :created_at, :presence => true # have another property to test if we mix up.
33
+
34
+ property :artist do
35
+ property :name
36
+ validates_uniqueness_of :name # this currently also tests if Form::AR is included as a feature.
37
+ end
17
38
  end
18
39
 
19
- it { form.class.i18n_scope.must_equal :activerecord }
40
+ let (:form) { SongForm.new(Song.new(:artist => Artist.new)) }
20
41
 
21
- describe "UniquenessValidator" do
22
- # ActiveRecord::Schema.define do
23
- # create_table :artists do |table|
24
- # table.column :name, :string
25
- # table.timestamps
26
- # end
27
- # end
28
- # Artist.new(:name => "Racer X").save
42
+ it { form.class.i18n_scope.must_equal :activerecord }
29
43
 
30
- it "allows accessing the database" do
31
- end
44
+ it "allows accessing the database" do
45
+ end
32
46
 
33
- it "is valid when name is unique" do
34
- form.validate({"name" => "Paul Gilbert", "created_at" => "November 6, 1966"}).must_equal true
35
- end
47
+ # uniqueness
48
+ it "is valid when name is unique" do
49
+ form.validate("artist" => {"name" => "Paul Gilbert"}, "title" => "The Gargoyle", "created_at" => "November 6, 1966").must_equal true
50
+ end
36
51
 
37
- it "is invalid and shows error when taken" do
38
- Artist.create(:name => "Racer X")
52
+ # nested object taken.
53
+ it "is invalid and shows error when taken" do
54
+ Song.delete_all
55
+ Artist.create(:name => "Racer X")
39
56
 
40
- form.validate({"name" => "Racer X"}).must_equal false
41
- form.errors.messages.must_equal({:name=>["has already been taken"], :created_at => ["can't be blank"]})
42
- end
57
+ form.validate("artist" => {"name" => "Racer X"}, "title" => "Ghost Inside My Skin").must_equal false
58
+ form.errors.messages.must_equal({:"artist.name"=>["has already been taken"], :created_at => ["can't be blank"]})
59
+ end
43
60
 
44
- it "works with Composition" do
45
- form = Class.new(Reform::Form) do
46
- include Reform::Form::ActiveRecord
47
- include Reform::Form::Composition
61
+ it "works with Composition" do
62
+ form = Class.new(Reform::Form) do
63
+ include Reform::Form::ActiveRecord
64
+ include Reform::Form::Composition
48
65
 
49
- property :name, :on => :artist
50
- validates_uniqueness_of :name
51
- end.new(:artist => Artist.new)
66
+ property :name, :on => :artist
67
+ validates_uniqueness_of :name
68
+ end.new(:artist => Artist.new)
52
69
 
53
- Artist.create(:name => "Bad Religion")
54
- form.validate("name" => "Bad Religion").must_equal false
55
- end
70
+ Artist.create(:name => "Bad Religion")
71
+ form.validate("name" => "Bad Religion").must_equal false
56
72
  end
57
73
 
58
74
  describe "#save" do
59
75
  # TODO: test 1-n?
60
76
  it "calls model.save" do
61
77
  Artist.delete_all
62
- form.validate("name" => "Bad Religion")
78
+ form.validate("artist" => {"name" => "Bad Religion"}, "title" => "Ghost Inside My Skin")
63
79
  form.save
64
80
  Artist.where(:name => "Bad Religion").size.must_equal 1
65
81
  end
@@ -71,4 +87,134 @@ class ActiveRecordTest < MiniTest::Spec
71
87
  Artist.where(:name => "Bad Religion").size.must_equal 0
72
88
  end
73
89
  end
74
- end
90
+ end
91
+
92
+
93
+ class PopulateWithActiveRecordTest < MiniTest::Spec
94
+ class AlbumForm < Reform::Form
95
+ property :title
96
+
97
+ collection :songs, :populate_if_empty => Song do
98
+ property :title
99
+ end
100
+ end
101
+
102
+ let (:album) { Album.new(:songs => []) }
103
+ it do
104
+ form = AlbumForm.new(album)
105
+
106
+ form.validate("songs" => [{"title" => "Straight From The Jacket"}])
107
+
108
+ # form populated.
109
+ form.songs.size.must_equal 1
110
+ form.songs[0].model.must_be_kind_of Song
111
+
112
+ # model NOT populated.
113
+ album.songs.must_equal []
114
+
115
+
116
+ form.sync
117
+
118
+ # form populated.
119
+ form.songs.size.must_equal 1
120
+ form.songs[0].model.must_be_kind_of Song
121
+
122
+ # model also populated.
123
+ song = album.songs[0]
124
+ album.songs.must_equal [song]
125
+ song.title.must_equal "Straight From The Jacket"
126
+
127
+
128
+ if ActiveRecord::VERSION::STRING !~ /^3.0/
129
+ # saving saves association.
130
+ form.save
131
+
132
+ album.reload
133
+ song = album.songs[0]
134
+ album.songs.must_equal [song]
135
+ song.title.must_equal "Straight From The Jacket"
136
+ end
137
+ end
138
+
139
+
140
+ describe "modifying 1., adding 2." do
141
+ let (:song) { Song.new(:title => "Part 2") }
142
+ let (:album) { Album.create.tap { |a| a.songs << song } }
143
+
144
+ it do
145
+ form = AlbumForm.new(album)
146
+
147
+ id = album.songs[0].id
148
+ assert id > 0
149
+
150
+ form.validate("songs" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
151
+
152
+ # form populated.
153
+ form.songs.size.must_equal 2
154
+ form.songs[0].model.must_be_kind_of Song
155
+ form.songs[1].model.must_be_kind_of Song
156
+
157
+ # model NOT populated.
158
+ album.songs.must_equal [song]
159
+
160
+
161
+ form.sync
162
+
163
+ # form populated.
164
+ form.songs.size.must_equal 2
165
+
166
+ # model also populated.
167
+ album.songs.size.must_equal 2
168
+
169
+ # corrected title
170
+ album.songs[0].title.must_equal "Part Two"
171
+ # ..but same song.
172
+ album.songs[0].id.must_equal id
173
+
174
+ # and a new song.
175
+ album.songs[1].title.must_equal "Check For A Pulse"
176
+ album.songs[1].persisted?.must_equal true # TODO: with << strategy, this shouldn't be saved.
177
+ end
178
+ end
179
+
180
+ # it do
181
+ # a=Album.new
182
+ # a.songs << Song.new(title: "Old What's His Name") # Song does not get persisted.
183
+
184
+ # a.songs[1] = Song.new(title: "Permanent Rust")
185
+
186
+ # puts "@@@"
187
+ # puts a.songs.inspect
188
+
189
+ # puts "---"
190
+ # a.save
191
+ # puts a.songs.inspect
192
+
193
+
194
+
195
+ # b = a.songs.first
196
+
197
+ # a.songs = [Song.new(title:"Biomag")]
198
+ # puts "\\\\"
199
+ # a.save
200
+ # a.reload
201
+ # puts a.songs.inspect
202
+
203
+ # b.reload
204
+ # puts "#{b.inspect}, #{b.persisted?}"
205
+
206
+
207
+ # a.songs = [a.songs.first, Song.new(title: "Count Down")]
208
+ # b = a.songs.first
209
+ # puts ":::::"
210
+ # a.save
211
+ # a.reload
212
+ # puts a.songs.inspect
213
+
214
+ # b.reload
215
+ # puts "#{b.inspect}, #{b.persisted?}"
216
+ # end
217
+ end
218
+
219
+
220
+
@@ -65,7 +65,7 @@ class AsTest < BaseTest
65
65
  it do
66
66
  hash = nil
67
67
 
68
- subject.save do |f, nested_hash|
68
+ subject.save do |nested_hash|
69
69
  hash = nested_hash
70
70
  end
71
71
 
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ class BuilderTest < MiniTest::Spec
4
+ it do
5
+ Builder.new.checkboxes(:settings, :hash => {"play" => true, "released" => false}).must_equal %{<input name="yo" type="hidden" value="unchecked_value" /><input id="object_name_method" name="yo" type="checkbox" value="checked_value" />
6
+ <input name="yo" type="hidden" value="unchecked_value" /><input id="object_name_method" name="yo" type="checkbox" value="checked_value" />}
7
+ end
8
+ end
9
+
10
+
11
+ require 'action_view/helpers/capture_helper'
12
+ require 'action_view/helpers/tag_helper'
13
+ require 'action_view/helpers/url_helper'
14
+ require 'action_view/helpers/sanitize_helper'
15
+ require 'action_view/helpers/text_helper'
16
+ require 'action_view/helpers/form_tag_helper'
17
+ require 'action_view/helpers/form_helper'
18
+
19
+ class Builder
20
+ include ActionView::Helpers::CaptureHelper
21
+ include ActionView::Helpers::FormHelper
22
+
23
+ # {name: value}
24
+ def checkboxes(name, options)
25
+ # get property form.to_a ? to_builder_hash or something like that
26
+ options[:hash].collect do |id, value|
27
+ ActionView::Helpers::InstanceTag.new(:object_name, :method, self).to_check_box_tag({:name => "yo"}, :checked_value, :unchecked_value)
28
+
29
+ # check_box_tag(id, value, checked = false, {})
30
+ end.join("\n")
31
+ end
32
+ end
@@ -2,43 +2,71 @@ require "test_helper"
2
2
  require "reform/form/coercion"
3
3
 
4
4
  class CoercionTest < BaseTest
5
- subject do
6
- Class.new(Reform::Form) do
7
- include Reform::Form::Coercion
5
+ class Irreversible < Virtus::Attribute
6
+ def coerce(value)
7
+ value*2
8
+ end
9
+ end
8
10
 
9
- property :released_at, :type => DateTime
11
+ class Form < Reform::Form
12
+ include Coercion
10
13
 
11
- property :hit do
12
- property :length, :type => Integer
13
- property :good, :type => Virtus::Attribute::Boolean
14
- end
14
+ property :released_at, :type => DateTime
15
+
16
+ property :hit do
17
+ # include Coercion
18
+ property :length, :type => Integer
19
+ property :good, :type => Virtus::Attribute::Boolean
20
+ end
15
21
 
16
- property :band do
17
- property :label do
18
- property :value, :type => Float
19
- end
22
+ property :band do
23
+ include Coercion
24
+ property :label do
25
+ include Coercion
26
+ property :value, :type => Irreversible
20
27
  end
21
- end.new(OpenStruct.new(
22
- :released_at => "31/03/1981",
23
- :hit => OpenStruct.new(:length => "312"),
24
- :band => Band.new(OpenStruct.new(:value => "9999.99"))
25
- ))
28
+ end
26
29
  end
27
30
 
28
- it { subject.released_at.must_be_kind_of DateTime }
29
- it { subject.released_at.must_equal DateTime.parse("Tue, 31 Mar 1981 00:00:00 +0000") }
30
- it { subject.hit.length.must_equal 312 }
31
- it { subject.band.label.value.must_equal 9999.99 }
31
+ subject do
32
+ Form.new(album)
33
+ end
32
34
 
35
+ let (:album) {
36
+ OpenStruct.new(
37
+ :released_at => "31/03/1981",
38
+ :hit => OpenStruct.new(:length => "312"),
39
+ :band => Band.new(OpenStruct.new(:value => "9999.99"))
40
+ )
41
+ }
33
42
 
34
- it "allows coercion in validate" do
35
- form = Class.new(Reform::Form) do
36
- include Reform::Form::Coercion
43
+ # it { subject.released_at.must_be_kind_of DateTime }
44
+ it { subject.released_at.must_equal "31/03/1981" } # NO coercion in setup.
45
+ it { subject.hit.length.must_equal "312" }
46
+ it { subject.band.label.value.must_equal "9999.99" }
37
47
 
38
- property :id, :type => Integer
39
- end.new(OpenStruct.new())
40
48
 
41
- form.validate("id" => "1")
42
- form.id.must_equal 1
49
+ let (:params) {
50
+ {
51
+ :released_at => "30/03/1981",
52
+ :hit => {:length => "312"},
53
+ :band => {:label => {:value => "9999.99"}}
54
+ }
55
+ }
56
+
57
+
58
+ # validate
59
+ describe "#validate" do
60
+ before { subject.validate(params) }
61
+
62
+ it { subject.released_at.must_equal DateTime.parse("30/03/1981") }
63
+ it { subject.hit.length.must_equal 312 }
64
+ it { subject.hit.good.must_equal nil }
65
+ it { subject.band.label.value.must_equal "9999.999999.99" } # coercion happened once.
43
66
  end
67
+
68
+ # save
69
+
70
+
71
+
44
72
  end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+ require 'representable/json'
3
+
4
+ class DeserializeTest < BaseTest
5
+ class AlbumContract < Reform::Form
6
+ self.representer_class.class_eval do
7
+ include Representable::JSON
8
+ end
9
+ def deserialize_method
10
+ :from_json
11
+ end
12
+
13
+ property :title
14
+ validates :title, :presence => true, :length => {:minimum => 3}
15
+
16
+ property :hit do
17
+ property :title
18
+ validates :title, :presence => true
19
+ end
20
+
21
+ property :band do # yepp, people do crazy stuff like that.
22
+ validates :label, :presence => true
23
+
24
+ property :label do
25
+ property :name
26
+ validates :name, :presence => true
27
+ end
28
+ end
29
+ end
30
+
31
+ let (:album) { Album.new(nil, Song.new, [Song.new, Song.new], Band.new(Label.new("Fat Wreck")) ) }
32
+ subject { AlbumContract.new(album) }
33
+
34
+ let (:json) { '{"hit":{"title":"Sacrifice"},"title":"Second Heat","songs":[{"title":"Heart Of A Lion"}],"band":{"label":{"name":"Fat Wreck"}}}' }
35
+
36
+ it {
37
+ subject.validate(json)
38
+ subject.band.label.name.must_equal "Fat Wreck"
39
+ }
40
+ end
@@ -12,7 +12,7 @@ class FormBuilderCompatTest < BaseTest
12
12
 
13
13
  collection :songs do
14
14
  property :title
15
- property :release_date
15
+ property :release_date, :multi_params => true
16
16
  validates :title, :presence => true
17
17
  end
18
18