reform 2.0.0 → 2.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 247ffc53838f5e69a71f4ab5d066572b05308003
4
- data.tar.gz: f6162c6a018e02ad2f9c487441dcea08623b960a
3
+ metadata.gz: 037b79d11746474c6c396824536f8bd567e59879
4
+ data.tar.gz: 4d448833f2cde88977600d0e9cc85686550eeda8
5
5
  SHA512:
6
- metadata.gz: 31ee6b2d4656b94ced0c7790832e8b6be84ea2b8218866c5cb9e75c6b3099710e9e2a52a24cd54b9c40ba0ead9a9712e7e961ac4b463f48bb34131b305c22246
7
- data.tar.gz: d8954f5806cdbbd701b4e8352d930f2b1bd3aef5a36d5621ef154a0132e6e46481137b5f1d9208932a0377805f81cac75ee066885cf73b2ea4778957e8c1192b
6
+ metadata.gz: a40d0cde85b16d5b4f4fbfa06cde1549e961044986abda2a95cb0abc2a22224a8b0b7dd88a7e80706b9b78b1932056d0091d4c858f7d3e67b523ced40bdd1285
7
+ data.tar.gz: bc964b5838dabcaac8b47db139a6a6b86c624b133297af97489d6dd1f465bb375cb47c9186c52832ad4ebea03227095f0947629edfc3678090fd471e2e06ff66
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 2.0.1
2
+
3
+ * Fix `ActiveModel::Validations` where translations in custom validations would error. This is now handled by delegating back to the `Valiator` object in Reform.
4
+
1
5
  ## 2.0.0
2
6
 
3
7
  * The `::reform_2_0!` is no longer there. Guess why.
data/README.md CHANGED
@@ -113,8 +113,12 @@ It's then up to you what to do with the updated models - they're still unsaved.
113
113
  The easiest way to save the data is to call `#save` on the form.
114
114
 
115
115
  ```ruby
116
- @form.save #=> populates album with incoming data
117
- # by calling @form.album.title=.
116
+ if @form.validate(params[:song])
117
+ @form.save #=> populates album with incoming data
118
+ # by calling @form.album.title=.
119
+ else
120
+ # handle validation errors.
121
+ end
118
122
  ```
119
123
 
120
124
  This will sync the data to the model and then call `album.save`.
Binary file
@@ -5,13 +5,16 @@ require "uber/delegates"
5
5
  module Reform::Form::ActiveModel
6
6
  # AM::Validations for your form.
7
7
  #
8
- # Note: The preferred way for validations should be Lotus::Validations, as ActiveModel::Validation's implementation is
9
- # old, very complex given that it needs to do a simple thing, and it's using globals like @errors.
8
+ # Note: The preferred way for validations should be Lotus::Validations, as ActiveModel::Validation's
9
+ # implementation is old, very complex given that it needs to do a simple thing, is using
10
+ # globals like @errors, and relies and more than 100 methods to be mixed into your form.
10
11
  #
11
12
  # Implements ::validates and friends, and #valid?.
13
+ #
12
14
  module Validations
13
15
  def self.included(includer)
14
16
  includer.instance_eval do
17
+ include Reform::Form::ActiveModel
15
18
  extend Uber::InheritableAttr
16
19
  inheritable_attr :validator
17
20
  self.validator = Class.new(Validator)
@@ -19,6 +22,9 @@ module Reform::Form::ActiveModel
19
22
  class << self
20
23
  extend Uber::Delegates
21
24
  delegates :validator, :validates, :validate, :validates_with, :validate_with
25
+
26
+ # Hooray! Delegate translation back to Reform's Validator class which contains AM::Validations.
27
+ delegates :validator, :human_attribute_name, :lookup_ancestors, :i18n_scope # Rails 3.1.
22
28
  end
23
29
  end
24
30
  end
@@ -27,6 +33,12 @@ module Reform::Form::ActiveModel
27
33
  Reform::Contract::Errors.new(self)
28
34
  end
29
35
 
36
+ # The concept of "composition" has still not arrived in Rails core and they rely on 400 methods being
37
+ # available in one object. This is why we need to provide parts of the I18N API in the form.
38
+ def read_attribute_for_validation(name)
39
+ send(name)
40
+ end
41
+
30
42
 
31
43
  # Validators is the validatable object. On the class level, we define validations,
32
44
  # on instance, it exposes #valid?.
@@ -44,9 +56,6 @@ module Reform::Form::ActiveModel
44
56
  @form.send(method_name, *args, &block)
45
57
  end
46
58
 
47
- # def self.model_name # FIXME: this is only needed for i18n, it seems.
48
- # "Reform::Form"
49
- # end
50
59
  def self.model_name
51
60
  ActiveModel::Name.new(Reform::Form)
52
61
  end
@@ -57,7 +66,8 @@ module Reform::Form::ActiveModel
57
66
  end
58
67
  end
59
68
 
60
-
69
+ # Needs to be implemented by every validation backend and implements the
70
+ # actual validation. See Reform::Form::Lotus, too!
61
71
  def valid?
62
72
  validator = self.class.validator.new(self)
63
73
  validator.valid? # run the Validations object's validator with the form as context. this won't pollute anything in the form.
@@ -1,4 +1,4 @@
1
1
  require 'reform/form/active_model'
2
2
  require 'reform/form/orm'
3
3
  require 'reform/form/mongoid'
4
- require 'reform/form/model_reflections' # only load this in AR context as simple_form currently is bound to AR.
4
+ require 'reform/form/active_model/model_reflections' # only load this in AR context as simple_form currently is bound to AR.
@@ -1,3 +1,3 @@
1
1
  module Reform
2
- VERSION = "2.0.0"
2
+ VERSION = "2.0.1"
3
3
  end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ class ActiveModelCustomValidationTranslationsTest < MiniTest::Spec
4
+ module SongForm
5
+ class WithBlock < Reform::Form
6
+ property :title
7
+
8
+ validate do
9
+ errors.add :title, :blank
10
+ end
11
+ end
12
+
13
+ class WithLambda < Reform::Form
14
+ property :title
15
+
16
+ validate ->{ errors.add :title, :blank }
17
+ end
18
+
19
+ class WithMethod < Reform::Form
20
+ property :title
21
+
22
+ validate :custom_validation_method
23
+ def custom_validation_method
24
+ errors.add :title, :blank
25
+ end
26
+ end
27
+ end
28
+
29
+
30
+ it 'translates the error message when custom validation is used with block' do
31
+ form = SongForm::WithBlock.new(Song.new)
32
+ form.validate({})
33
+ form.errors[:title].must_include "can't be blank"
34
+ end
35
+
36
+ it 'translates the error message when custom validation is used with lambda' do
37
+ form = SongForm::WithLambda.new(Song.new)
38
+ form.validate({})
39
+ form.errors[:title].must_include "can't be blank"
40
+ end
41
+
42
+ it 'translates the error message when custom validation is used with method' do
43
+ form = SongForm::WithMethod.new(Song.new)
44
+ form.validate({})
45
+ form.errors[:title].must_include "can't be blank"
46
+ end
47
+ end
@@ -1,5 +1,205 @@
1
- # Sample localization file for English. Add more files in this directory for other locales.
2
- # See http://github.com/svenfuchs/rails-i18n/tree/master/rails%2Flocale for starting points.
3
-
1
+ ---
4
2
  en:
5
- hello: "Hello world"
3
+ date:
4
+ abbr_day_names:
5
+ - Sun
6
+ - Mon
7
+ - Tue
8
+ - Wed
9
+ - Thu
10
+ - Fri
11
+ - Sat
12
+ abbr_month_names:
13
+ -
14
+ - Jan
15
+ - Feb
16
+ - Mar
17
+ - Apr
18
+ - May
19
+ - Jun
20
+ - Jul
21
+ - Aug
22
+ - Sep
23
+ - Oct
24
+ - Nov
25
+ - Dec
26
+ day_names:
27
+ - Sunday
28
+ - Monday
29
+ - Tuesday
30
+ - Wednesday
31
+ - Thursday
32
+ - Friday
33
+ - Saturday
34
+ formats:
35
+ default: "%Y-%m-%d"
36
+ long: "%B %d, %Y"
37
+ short: "%b %d"
38
+ month_names:
39
+ -
40
+ - January
41
+ - February
42
+ - March
43
+ - April
44
+ - May
45
+ - June
46
+ - July
47
+ - August
48
+ - September
49
+ - October
50
+ - November
51
+ - December
52
+ order:
53
+ - :year
54
+ - :month
55
+ - :day
56
+ datetime:
57
+ distance_in_words:
58
+ about_x_hours:
59
+ one: about 1 hour
60
+ other: about %{count} hours
61
+ about_x_months:
62
+ one: about 1 month
63
+ other: about %{count} months
64
+ about_x_years:
65
+ one: about 1 year
66
+ other: about %{count} years
67
+ almost_x_years:
68
+ one: almost 1 year
69
+ other: almost %{count} years
70
+ half_a_minute: half a minute
71
+ less_than_x_minutes:
72
+ one: less than a minute
73
+ other: less than %{count} minutes
74
+ less_than_x_seconds:
75
+ one: less than 1 second
76
+ other: less than %{count} seconds
77
+ over_x_years:
78
+ one: over 1 year
79
+ other: over %{count} years
80
+ x_days:
81
+ one: 1 day
82
+ other: "%{count} days"
83
+ x_minutes:
84
+ one: 1 minute
85
+ other: "%{count} minutes"
86
+ x_months:
87
+ one: 1 month
88
+ other: "%{count} months"
89
+ x_seconds:
90
+ one: 1 second
91
+ other: "%{count} seconds"
92
+ prompts:
93
+ day: Day
94
+ hour: Hour
95
+ minute: Minute
96
+ month: Month
97
+ second: Seconds
98
+ year: Year
99
+ errors:
100
+ format: "%{attribute} %{message}"
101
+ messages:
102
+ accepted: must be accepted
103
+ blank: can't be blank
104
+ present: must be blank
105
+ confirmation: doesn't match %{attribute}
106
+ empty: can't be empty
107
+ equal_to: must be equal to %{count}
108
+ even: must be even
109
+ exclusion: is reserved
110
+ greater_than: must be greater than %{count}
111
+ greater_than_or_equal_to: must be greater than or equal to %{count}
112
+ inclusion: is not included in the list
113
+ invalid: is invalid
114
+ less_than: must be less than %{count}
115
+ less_than_or_equal_to: must be less than or equal to %{count}
116
+ not_a_number: is not a number
117
+ not_an_integer: must be an integer
118
+ odd: must be odd
119
+ record_invalid: 'Validation failed: %{errors}'
120
+ restrict_dependent_destroy:
121
+ one: Cannot delete record because a dependent %{record} exists
122
+ many: Cannot delete record because dependent %{record} exist
123
+ taken: has already been taken
124
+ too_long:
125
+ one: is too long (maximum is 1 character)
126
+ other: is too long (maximum is %{count} characters)
127
+ too_short:
128
+ one: is too short (minimum is 1 character)
129
+ other: is too short (minimum is %{count} characters)
130
+ wrong_length:
131
+ one: is the wrong length (should be 1 character)
132
+ other: is the wrong length (should be %{count} characters)
133
+ other_than: must be other than %{count}
134
+ template:
135
+ body: 'There were problems with the following fields:'
136
+ header:
137
+ one: 1 error prohibited this %{model} from being saved
138
+ other: "%{count} errors prohibited this %{model} from being saved"
139
+ helpers:
140
+ select:
141
+ prompt: Please select
142
+ submit:
143
+ create: Create %{model}
144
+ submit: Save %{model}
145
+ update: Update %{model}
146
+ number:
147
+ currency:
148
+ format:
149
+ delimiter: ","
150
+ format: "%u%n"
151
+ precision: 2
152
+ separator: "."
153
+ significant: false
154
+ strip_insignificant_zeros: false
155
+ unit: "$"
156
+ format:
157
+ delimiter: ","
158
+ precision: 3
159
+ separator: "."
160
+ significant: false
161
+ strip_insignificant_zeros: false
162
+ human:
163
+ decimal_units:
164
+ format: "%n %u"
165
+ units:
166
+ billion: Billion
167
+ million: Million
168
+ quadrillion: Quadrillion
169
+ thousand: Thousand
170
+ trillion: Trillion
171
+ unit: ''
172
+ format:
173
+ delimiter: ''
174
+ precision: 3
175
+ significant: true
176
+ strip_insignificant_zeros: true
177
+ storage_units:
178
+ format: "%n %u"
179
+ units:
180
+ byte:
181
+ one: Byte
182
+ other: Bytes
183
+ gb: GB
184
+ kb: KB
185
+ mb: MB
186
+ tb: TB
187
+ percentage:
188
+ format:
189
+ delimiter: ''
190
+ format: "%n%"
191
+ precision:
192
+ format:
193
+ delimiter: ''
194
+ support:
195
+ array:
196
+ last_word_connector: ", and "
197
+ two_words_connector: " and "
198
+ words_connector: ", "
199
+ time:
200
+ am: am
201
+ formats:
202
+ default: "%a, %d %b %Y %H:%M:%S %z"
203
+ long: "%B %d, %Y %H:%M"
204
+ short: "%d %b %H:%M"
205
+ pm: pm
@@ -1,311 +1,313 @@
1
- # require 'test_helper'
2
- # def mongoid_present?
3
- # require 'mongoid'
4
- # Mongoid.configure do |config|
5
- # config.connect_to("reform-mongoid-test")
6
- # end
7
- # true
8
- # rescue
9
- # false
10
- # end
11
-
12
- # if mongoid_present?
13
- # require 'reform/mongoid'
14
-
15
- # class Disc
16
- # include Mongoid::Document
17
- # field :title, type: String
18
- # has_many :tunes
19
- # has_and_belongs_to_many :musicians
20
- # end
21
-
22
- # class Musician
23
- # include Mongoid::Document
24
- # field :name, type: String
25
- # end
26
-
27
- # class Tune
28
- # include Mongoid::Document
29
- # include Mongoid::Timestamps
30
- # field :title, type: String
31
- # belongs_to :disc
32
- # belongs_to :musician
33
- # end
34
-
35
- # class MongoidTest < MiniTest::Spec
36
- # class TuneForm < Reform::Form
37
- # include Reform::Form::Mongoid
38
- # model :tune
39
-
40
- # property :title
41
- # property :created_at
42
-
43
- # validates_uniqueness_of :title, scope: [:disc_id, :musician_id]
44
- # validates :created_at, :presence => true # have another property to test if we mix up.
45
-
46
- # property :musician do
47
- # property :name
48
- # validates_uniqueness_of :name # this currently also tests if Form::AR is included as a feature.
49
- # end
50
- # end
51
-
52
- # let(:disc) { Disc.create(:title => "Damnation") }
53
- # let(:musician) { Musician.create(:name => "Opeth") }
54
- # let(:form) { TuneForm.new(Tune.new(:musician => Musician.new)) }
55
-
56
- # it { form.class.i18n_scope.must_equal :mongoid }
57
-
58
- # it "allows accessing the database" do
59
- # end
60
-
61
- # # uniqueness
62
- # it "has no errors on title when title is unique for the same musician and disc" do
63
- # form.validate("title" => "The Gargoyle", "musician_id" => musician.id, "disc" => disc.id, "created_at" => "November 6, 1966")
64
- # assert_empty form.errors[:title]
65
- # end
66
-
67
- # it "has errors on title when title is taken for the same musician and disc" do
68
- # skip "replace ActiveModel::Validations with our own, working and reusable gem."
69
- # Tune.create(title: "Windowpane", musician_id: musician.id, disc_id: disc.id)
70
- # form.validate("title" => "Windowpane", "musician_id" => musician.id, "disc" => disc)
71
- # refute_empty form.errors[:title]
72
- # end
73
-
74
- # # nested object taken.
75
- # it "is valid when musician name is unique" do
76
- # form.validate("musician" => {"name" => "Paul Gilbert"}, "title" => "The Gargoyle", "created_at" => "November 6, 1966").must_equal true
77
- # end
78
-
79
- # it "is invalid and shows error when taken" do
80
- # Tune.delete_all
81
- # Musician.create(:name => "Racer X")
82
-
83
- # form.validate("musician" => {"name" => "Racer X"}, "title" => "Ghost Inside My Skin").must_equal false
84
- # form.errors.messages.must_equal({:"musician.name"=>["is already taken"], :created_at => ["can't be blank"]})
85
- # end
86
-
87
- # it "works with Composition" do
88
- # form = Class.new(Reform::Form) do
89
- # include Reform::Form::Mongoid
90
- # include Reform::Form::Composition
91
-
92
- # property :name, :on => :musician
93
- # validates_uniqueness_of :name
94
- # end.new(:musician => Musician.new)
95
-
96
- # Musician.create(:name => "Bad Religion")
97
- # form.validate("name" => "Bad Religion").must_equal false
98
- # end
99
-
100
- # describe "#save" do
101
- # # TODO: test 1-n?
102
- # it "calls model.save" do
103
- # Musician.delete_all
104
- # form.validate("musician" => {"name" => "Bad Religion"}, "title" => "Ghost Inside My Skin")
105
- # form.save
106
- # Musician.where(:name => "Bad Religion").size.must_equal 1
107
- # end
108
-
109
- # it "doesn't call model.save when block is given" do
110
- # Musician.delete_all
111
- # form.validate("name" => "Bad Religion")
112
- # form.save {}
113
- # Musician.where(:name => "Bad Religion").size.must_equal 0
114
- # end
115
- # end
116
- # end
1
+ require 'test_helper'
2
+ def mongoid_present?
3
+ require 'mongoid'
4
+ Mongoid.configure do |config|
5
+ config.connect_to("reform-mongoid-test")
6
+ end
7
+ true
8
+ rescue
9
+ false
10
+ end
11
+
12
+ if mongoid_present?
13
+ require 'reform/mongoid'
14
+
15
+ class Disc
16
+ include Mongoid::Document
17
+ field :title, type: String
18
+ has_many :tunes
19
+ has_and_belongs_to_many :musicians
20
+ end
21
+
22
+ class Musician
23
+ include Mongoid::Document
24
+ field :name, type: String
25
+ end
26
+
27
+ class Tune
28
+ include Mongoid::Document
29
+ include Mongoid::Timestamps
30
+ field :title, type: String
31
+ belongs_to :disc
32
+ belongs_to :musician
33
+ end
34
+
35
+ class MongoidTest < MiniTest::Spec
36
+ class TuneForm < Reform::Form
37
+ include Reform::Form::Mongoid
38
+ model :tune
39
+
40
+ property :title
41
+ property :created_at
42
+
43
+ validates_uniqueness_of :title, scope: [:disc_id, :musician_id]
44
+ validates :created_at, :presence => true # have another property to test if we mix up.
45
+
46
+ property :musician do
47
+ property :name
48
+ validates_uniqueness_of :name # this currently also tests if Form::AR is included as a feature.
49
+ end
50
+ end
51
+
52
+ let(:disc) { Disc.create(:title => "Damnation") }
53
+ let(:musician) { Musician.create(:name => "Opeth") }
54
+ let(:form) { TuneForm.new(Tune.new(:musician => Musician.new)) }
55
+
56
+ it { form.class.i18n_scope.must_equal :mongoid }
57
+
58
+ it "allows accessing the database" do
59
+ end
60
+
61
+ # uniqueness
62
+ it "has no errors on title when title is unique for the same musician and disc" do
63
+ form.validate("title" => "The Gargoyle", "musician_id" => musician.id, "disc" => disc.id, "created_at" => "November 6, 1966")
64
+ assert_empty form.errors[:title]
65
+ end
66
+
67
+ it "has errors on title when title is taken for the same musician and disc" do
68
+ skip "replace ActiveModel::Validations with our own, working and reusable gem."
69
+ Tune.create(title: "Windowpane", musician_id: musician.id, disc_id: disc.id)
70
+ form.validate("title" => "Windowpane", "musician_id" => musician.id, "disc" => disc)
71
+ refute_empty form.errors[:title]
72
+ end
73
+
74
+ # nested object taken.
75
+ it "is valid when musician name is unique" do
76
+ form.validate("musician" => {"name" => "Paul Gilbert"}, "title" => "The Gargoyle", "created_at" => "November 6, 1966").must_equal true
77
+ end
78
+
79
+ it "is invalid and shows error when taken" do
80
+ Tune.delete_all
81
+ Musician.create(:name => "Racer X")
82
+
83
+ form.validate("musician" => {"name" => "Racer X"}, "title" => "Ghost Inside My Skin").must_equal false
84
+ form.errors.messages.must_equal({:"musician.name"=>["is already taken"], :created_at => ["can't be blank"]})
85
+ end
86
+
87
+ it "works with Composition" do
88
+ form = Class.new(Reform::Form) do
89
+ include Reform::Form::Mongoid
90
+ include Reform::Form::Composition
91
+
92
+ property :name, :on => :musician
93
+ validates_uniqueness_of :name
94
+ end.new(:musician => Musician.new)
95
+
96
+ Musician.create(:name => "Bad Religion")
97
+ form.validate("name" => "Bad Religion").must_equal false
98
+ end
99
+
100
+ describe "#save" do
101
+ # TODO: test 1-n?
102
+ it "calls model.save" do
103
+ Musician.delete_all
104
+ form.validate("musician" => {"name" => "Bad Religion"}, "title" => "Ghost Inside My Skin")
105
+ form.save
106
+ Musician.where(:name => "Bad Religion").size.must_equal 1
107
+ end
108
+
109
+ it "doesn't call model.save when block is given" do
110
+ Musician.delete_all
111
+ form.validate("name" => "Bad Religion")
112
+ form.save {}
113
+ Musician.where(:name => "Bad Religion").size.must_equal 0
114
+ end
115
+ end
116
+ end
117
+
117
118
 
119
+ class PopulateWithActiveRecordTest < MiniTest::Spec
120
+ class DiscForm < Reform::Form
118
121
 
119
- # class PopulateWithActiveRecordTest < MiniTest::Spec
120
- # class DiscForm < Reform::Form
122
+ property :title
121
123
 
122
- # property :title
124
+ collection :tunes, :populate_if_empty => Tune do
125
+ property :title
126
+ end
127
+ end
123
128
 
124
- # collection :tunes, :populate_if_empty => Tune do
125
- # property :title
126
- # end
127
- # end
129
+ let (:disc) { Disc.new(:tunes => []) }
130
+ it do
131
+ form = DiscForm.new(disc)
128
132
 
129
- # let (:disc) { Disc.new(:tunes => []) }
130
- # it do
131
- # form = DiscForm.new(disc)
133
+ form.validate("tunes" => [{"title" => "Straight From The Jacket"}])
132
134
 
133
- # form.validate("tunes" => [{"title" => "Straight From The Jacket"}])
135
+ # form populated.
136
+ form.tunes.size.must_equal 1
137
+ form.tunes[0].model.must_be_kind_of Tune
134
138
 
135
- # # form populated.
136
- # form.tunes.size.must_equal 1
137
- # form.tunes[0].model.must_be_kind_of Tune
139
+ # model NOT populated.
140
+ disc.tunes.must_equal []
138
141
 
139
- # # model NOT populated.
140
- # disc.tunes.must_equal []
141
142
 
143
+ form.sync
142
144
 
143
- # form.sync
145
+ # form populated.
146
+ form.tunes.size.must_equal 1
147
+ form.tunes[0].model.must_be_kind_of Tune
144
148
 
145
- # # form populated.
146
- # form.tunes.size.must_equal 1
147
- # form.tunes[0].model.must_be_kind_of Tune
149
+ # model also populated.
150
+ tune = disc.tunes[0]
151
+ disc.tunes.must_equal [tune]
152
+ tune.title.must_equal "Straight From The Jacket"
148
153
 
149
- # # model also populated.
150
- # tune = disc.tunes[0]
151
- # disc.tunes.must_equal [tune]
152
- # tune.title.must_equal "Straight From The Jacket"
153
154
 
155
+ # if ActiveRecord::VERSION::STRING !~ /^3.0/
156
+ # # saving saves association.
157
+ # form.save
158
+ #
159
+ # disc.reload
160
+ # tune = disc.tunes[0]
161
+ # disc.tunes.must_equal [tune]
162
+ # tune.title.must_equal "Straight From The Jacket"
163
+ # end
164
+ end
154
165
 
155
- # # if ActiveRecord::VERSION::STRING !~ /^3.0/
156
- # # # saving saves association.
157
- # # form.save
158
- # #
159
- # # disc.reload
160
- # # tune = disc.tunes[0]
161
- # # disc.tunes.must_equal [tune]
162
- # # tune.title.must_equal "Straight From The Jacket"
163
- # # end
164
- # end
165
166
 
167
+ describe "modifying 1., adding 2." do
168
+ let (:tune) { Tune.new(:title => "Part 2") }
169
+ let (:disc) { Disc.create.tap { |a| a.tunes << tune } }
166
170
 
167
- # describe "modifying 1., adding 2." do
168
- # let (:tune) { Tune.new(:title => "Part 2") }
169
- # let (:disc) { Disc.create.tap { |a| a.tunes << tune } }
171
+ it do
172
+ form = DiscForm.new(disc)
170
173
 
171
- # it do
172
- # form = DiscForm.new(disc)
174
+ id = disc.tunes[0].id
175
+ disc.tunes[0].persisted?.must_equal true
176
+ assert id.to_s.size > 0
173
177
 
174
- # id = disc.tunes[0].id
175
- # assert id > 0
178
+ form.validate("tunes" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
176
179
 
177
- # form.validate("tunes" => [{"title" => "Part Two"}, {"title" => "Check For A Pulse"}])
180
+ # form populated.
181
+ form.tunes.size.must_equal 2
182
+ form.tunes[0].model.must_be_kind_of Tune
183
+ form.tunes[1].model.must_be_kind_of Tune
178
184
 
179
- # # form populated.
180
- # form.tunes.size.must_equal 2
181
- # form.tunes[0].model.must_be_kind_of Tune
182
- # form.tunes[1].model.must_be_kind_of Tune
185
+ # model NOT populated.
186
+ disc.tunes.must_equal [tune]
183
187
 
184
- # # model NOT populated.
185
- # disc.tunes.must_equal [tune]
186
188
 
189
+ form.sync
187
190
 
188
- # form.sync
191
+ # form populated.
192
+ form.tunes.size.must_equal 2
189
193
 
190
- # # form populated.
191
- # form.tunes.size.must_equal 2
194
+ # model also populated.
195
+ disc.tunes.size.must_equal 2
192
196
 
193
- # # model also populated.
194
- # disc.tunes.size.must_equal 2
197
+ # corrected title
198
+ disc.tunes[0].title.must_equal "Part Two"
199
+ # ..but same tune.
200
+ disc.tunes[0].id.must_equal id
195
201
 
196
- # # corrected title
197
- # disc.tunes[0].title.must_equal "Part Two"
198
- # # ..but same tune.
199
- # disc.tunes[0].id.must_equal id
202
+ # and a new tune.
203
+ disc.tunes[1].title.must_equal "Check For A Pulse"
204
+ disc.tunes[1].persisted?.must_equal true # TODO: with << strategy, this shouldn't be saved.
205
+ end
200
206
 
201
- # # and a new tune.
202
- # disc.tunes[1].title.must_equal "Check For A Pulse"
203
- # disc.tunes[1].persisted?.must_equal true # TODO: with << strategy, this shouldn't be saved.
204
- # end
207
+ describe 'using nested_models_attributes to modify nested collection' do
208
+ class ActiveModelDiscForm < Reform::Form
209
+ include Reform::Form::ActiveModel
210
+ include Reform::Form::ActiveModel::FormBuilderMethods
205
211
 
206
- # describe 'using nested_models_attributes to modify nested collection' do
207
- # class ActiveModelDiscForm < Reform::Form
208
- # include Reform::Form::ActiveModel
209
- # include Reform::Form::ActiveModel::FormBuilderMethods
212
+ property :title
210
213
 
211
- # property :title
214
+ collection :tunes, :populate_if_empty => Tune do
215
+ property :title
216
+ end
217
+ end
212
218
 
213
- # collection :tunes, :populate_if_empty => Tune do
214
- # property :title
215
- # end
216
- # end
219
+ let (:disc) { Disc.create(:title => 'Greatest Hits') }
220
+ let (:form) { ActiveModelDiscForm.new(disc) }
217
221
 
218
- # let (:disc) { Disc.create(:title => 'Greatest Hits') }
219
- # let (:form) { ActiveModelDiscForm.new(disc) }
222
+ it do
223
+ form.validate('tunes_attributes' => {'0' => {'title' => 'Tango'}})
220
224
 
221
- # it do
222
- # form.validate('tunes_attributes' => {'0' => {'title' => 'Tango'}})
225
+ # form populated.
226
+ form.tunes.size.must_equal 1
227
+ form.tunes[0].model.must_be_kind_of Tune
228
+ form.tunes[0].title.must_equal 'Tango'
223
229
 
224
- # # form populated.
225
- # form.tunes.size.must_equal 1
226
- # form.tunes[0].model.must_be_kind_of Tune
227
- # form.tunes[0].title.must_equal 'Tango'
230
+ # model NOT populated.
231
+ disc.tunes.must_equal []
228
232
 
229
- # # model NOT populated.
230
- # disc.tunes.must_equal []
233
+ form.save
231
234
 
232
- # form.save
235
+ # nested model persisted.
236
+ first_tune = disc.tunes[0]
237
+ first_tune.persisted?.must_equal true
238
+ assert first_tune.id.to_s.size > 0
233
239
 
234
- # # nested model persisted.
235
- # first_tune = disc.tunes[0]
236
- # assert first_tune.id > 0
240
+ # form populated.
241
+ form.tunes.size.must_equal 1
237
242
 
238
- # # form populated.
239
- # form.tunes.size.must_equal 1
243
+ # model also populated.
244
+ disc.tunes.size.must_equal 1
245
+ disc.tunes[0].title.must_equal 'Tango'
240
246
 
241
- # # model also populated.
242
- # disc.tunes.size.must_equal 1
243
- # disc.tunes[0].title.must_equal 'Tango'
247
+ form = ActiveModelDiscForm.new(disc)
248
+ form.validate('tunes_attributes' => {'0' => {'id' => first_tune.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
244
249
 
245
- # form = ActiveModelDiscForm.new(disc)
246
- # form.validate('tunes_attributes' => {'0' => {'id' => first_tune.id, 'title' => 'Tango nuevo'}, '1' => {'title' => 'Waltz'}})
250
+ # form populated.
251
+ form.tunes.size.must_equal 2
252
+ form.tunes[0].model.must_be_kind_of Tune
253
+ form.tunes[1].model.must_be_kind_of Tune
254
+ form.tunes[0].title.must_equal 'Tango nuevo'
255
+ form.tunes[1].title.must_equal 'Waltz'
247
256
 
248
- # # form populated.
249
- # form.tunes.size.must_equal 2
250
- # form.tunes[0].model.must_be_kind_of Tune
251
- # form.tunes[1].model.must_be_kind_of Tune
252
- # form.tunes[0].title.must_equal 'Tango nuevo'
253
- # form.tunes[1].title.must_equal 'Waltz'
257
+ # model NOT populated.
258
+ disc.tunes.size.must_equal 1
259
+ disc.tunes[0].title.must_equal 'Tango'
254
260
 
255
- # # model NOT populated.
256
- # disc.tunes.size.must_equal 1
257
- # disc.tunes[0].title.must_equal 'Tango'
261
+ form.save
258
262
 
259
- # form.save
263
+ # form populated.
264
+ form.tunes.size.must_equal 2
260
265
 
261
- # # form populated.
262
- # form.tunes.size.must_equal 2
266
+ # model also populated.
267
+ disc.tunes.size.must_equal 2
268
+ disc.tunes[0].id.must_equal first_tune.id
269
+ disc.tunes[0].persisted?.must_equal true
270
+ disc.tunes[1].persisted?.must_equal true
271
+ disc.tunes[0].title.must_equal 'Tango nuevo'
272
+ disc.tunes[1].title.must_equal 'Waltz'
273
+ end
274
+ end
275
+ end
263
276
 
264
- # # model also populated.
265
- # disc.tunes.size.must_equal 2
266
- # disc.tunes[0].id.must_equal first_tune.id
267
- # disc.tunes[0].persisted?.must_equal true
268
- # disc.tunes[1].persisted?.must_equal true
269
- # disc.tunes[0].title.must_equal 'Tango nuevo'
270
- # disc.tunes[1].title.must_equal 'Waltz'
271
- # end
272
- # end
273
- # end
277
+ # it do
278
+ # a=Disc.new
279
+ # a.tunes << Tune.new(title: "Old What's His Name") # Tune does not get persisted.
274
280
 
275
- # # it do
276
- # # a=Disc.new
277
- # # a.tunes << Tune.new(title: "Old What's His Name") # Tune does not get persisted.
281
+ # a.tunes[1] = Tune.new(title: "Permanent Rust")
278
282
 
279
- # # a.tunes[1] = Tune.new(title: "Permanent Rust")
283
+ # puts "@@@"
284
+ # puts a.tunes.inspect
280
285
 
281
- # # puts "@@@"
282
- # # puts a.tunes.inspect
286
+ # puts "---"
287
+ # a.save
288
+ # puts a.tunes.inspect
283
289
 
284
- # # puts "---"
285
- # # a.save
286
- # # puts a.tunes.inspect
290
+ # b = a.tunes.first
287
291
 
288
- # # b = a.tunes.first
292
+ # a.tunes = [Tune.new(title:"Biomag")]
293
+ # puts "\\\\"
294
+ # a.save
295
+ # a.reload
296
+ # puts a.tunes.inspect
297
+
298
+ # b.reload
299
+ # puts "#{b.inspect}, #{b.persisted?}"
289
300
 
290
- # # a.tunes = [Tune.new(title:"Biomag")]
291
- # # puts "\\\\"
292
- # # a.save
293
- # # a.reload
294
- # # puts a.tunes.inspect
295
301
 
296
- # # b.reload
297
- # # puts "#{b.inspect}, #{b.persisted?}"
302
+ # a.tunes = [a.tunes.first, Tune.new(title: "Count Down")]
303
+ # b = a.tunes.first
304
+ # puts ":::::"
305
+ # a.save
306
+ # a.reload
307
+ # puts a.tunes.inspect
298
308
 
299
-
300
- # # a.tunes = [a.tunes.first, Tune.new(title: "Count Down")]
301
- # # b = a.tunes.first
302
- # # puts ":::::"
303
- # # a.save
304
- # # a.reload
305
- # # puts a.tunes.inspect
306
-
307
- # # b.reload
308
- # # puts "#{b.inspect}, #{b.persisted?}"
309
- # # end
310
- # end
311
- # end
309
+ # b.reload
310
+ # puts "#{b.inspect}, #{b.persisted?}"
311
+ # end
312
+ end
313
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reform
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-07-10 00:00:00.000000000 Z
12
+ date: 2015-07-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: disposable
@@ -196,7 +196,6 @@ files:
196
196
  - Rakefile
197
197
  - TODO.md
198
198
  - database.sqlite3
199
- - gemfiles/Gemfile.rails-3.0
200
199
  - gemfiles/Gemfile.rails-3.1
201
200
  - gemfiles/Gemfile.rails-3.2
202
201
  - gemfiles/Gemfile.rails-4.0
@@ -230,6 +229,7 @@ files:
230
229
  - lib/reform/schema.rb
231
230
  - lib/reform/version.rb
232
231
  - reform.gemspec
232
+ - test/active_model_custom_validation_translations_test.rb
233
233
  - test/active_model_test.rb
234
234
  - test/active_record_test.rb
235
235
  - test/benchmarking.rb
@@ -319,6 +319,7 @@ signing_key:
319
319
  specification_version: 4
320
320
  summary: Form object decoupled from models with validation, population and presentation.
321
321
  test_files:
322
+ - test/active_model_custom_validation_translations_test.rb
322
323
  - test/active_model_test.rb
323
324
  - test/active_record_test.rb
324
325
  - test/benchmarking.rb
@@ -1,7 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in reform.gemspec
4
- gemspec :path => '../'
5
-
6
- gem 'railties', '~> 3.0.11'
7
- gem 'activerecord', '~> 3.0.11'