reform-rails 0.1.7 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: ef8e06973cbbd53737de0a7d0afe1250bdba0814
4
- data.tar.gz: 986c4d29338ecdc03fb3dea2ab7c75f6c9253ce6
2
+ SHA256:
3
+ metadata.gz: e32ac394ac02ea272b9a31655ca20b65253b8a417b0f716c7f1eda516c25981b
4
+ data.tar.gz: 7e520b5e80f4669f289bccaaa8cb5f3c549123d242e42a31e52f0be6e1f1086f
5
5
  SHA512:
6
- metadata.gz: 314925db393628f4f0d7a2dc32808217c7b2d17d0e27d86d69299b14df875917a1598857c291ea3eec8605bbcfb4e31e1d908c12df66ad3c4dd25a8fae6bc3ce
7
- data.tar.gz: 9f8f292731ef5b34f8abe6a046d738d18bd98b9192564ba592e8d922bfef02e0f61ba3feddee77d69cc2e590b4e91310bc925ec749fedbfcbee1b0ba458c0869
6
+ metadata.gz: 7b433bafad6faa28202c8a246c334fa2c7c41c735196b66f98353a9bf614990960278a2dccc87203a9985ad05e09077986795d7007e7d674e9938de3886c683d
7
+ data.tar.gz: 63f646b6f6bac1062176f84da317f05d0a44e58b0c9f3e9f5bfeb8573ceb25d2e659f84561ff831ee593f4f770494e991f49b046948036a67aa87eb2ab08b472
@@ -0,0 +1,28 @@
1
+ name: CI
2
+ on: [push, pull_request]
3
+ jobs:
4
+ test:
5
+ strategy:
6
+ fail-fast: false
7
+ matrix:
8
+ # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
9
+ ruby: [2.5, 2.6, 2.7, '3.0', head]
10
+ rails: ['6.1', '6.0', '5.2']
11
+ mongodb-version: ['4.4']
12
+ exclude:
13
+ - ruby: '3.0'
14
+ rails: 5.2
15
+ - ruby: head
16
+ rails: 5.2
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v2
20
+ - uses: supercharge/mongodb-github-action@1.6.0
21
+ with:
22
+ mongodb-version: ${{ matrix.mongodb-version }}
23
+ - uses: ruby/setup-ruby@v1
24
+ with:
25
+ ruby-version: ${{ matrix.ruby }}
26
+ # bundler-cache: true # runs 'bundle install' and caches installed gems automatically
27
+ - run: RAILS_VERSION=${{ matrix.rails }} bundle install
28
+ - run: RAILS_VERSION=${{ matrix.rails }} bundle exec rake
data/.gitignore CHANGED
@@ -8,4 +8,7 @@
8
8
  /spec/reports/
9
9
  /tmp/
10
10
  *.gem
11
- test/dummy/log/*.log
11
+ *.sqlite3
12
+ .byebug*
13
+ *.log
14
+ .rubocop-https*
data/CHANGES.md CHANGED
@@ -1,3 +1,46 @@
1
+ # 0.2.6
2
+
3
+ * Allow to override `#persisted?` and friends with modules.
4
+
5
+ # 0.2.5
6
+
7
+ * Fix: Delegating from form object causes ArgumentError with 0.2.4 (https://github.com/trailblazer/reform-rails/issues/99)
8
+
9
+ # 0.2.4
10
+
11
+ * Fix keyword argument warning in `method_missing` (https://github.com/trailblazer/reform-rails/pull/97)
12
+ * Internal: Replace Uber::Delegates with Forwardable in Form::ActiveModel
13
+
14
+ # 0.2.3
15
+
16
+ * Fix deprecation warning related to `respond_to?`
17
+
18
+ # 0.2.2
19
+
20
+ * Support ActiveRecord 6.1
21
+
22
+ # 0.2.1
23
+
24
+ * Error's full_message with translation fixed thanks to [@marcelolx](https://github.com/trailblazer/reform-rails/pull/85)
25
+
26
+ # 0.2.0
27
+
28
+ * Needs Reform >= 2.3.0.
29
+ * make the inclusion of ActiveModel form builder modules optional when using dry-validation. This can be controlled via `config.reform.enable_active_model_builder_methods = true`.
30
+ * delegate `validates_each` method and allow it to be called outside a validation block.
31
+ * add `case_sensitive` option to Reform Uniqueness validation. Defaults to true.
32
+ * fix bug in uniqueness validation where form has different attribute name to column
33
+ * improve handling of persisted records in uniqueness validator
34
+ * remove params.merge! as it's deprecated in rails 5
35
+ * update to support reform 2.3, the new API means that `errors.add` is delegated to ActiveModel::Errors to support rails 5
36
+ * Fix nested form validation (#53)
37
+ * Errors supports symbol and string lookup (PR #77)
38
+ * Implement respond_to that delegates to AMV errors (PR #78)
39
+ * Drop support for activemodel before 5.0
40
+
41
+ # 0.1.8
42
+ * Drop support to mongoid < 4.
43
+
1
44
  # 0.1.7 (0.1.6 Yanked)
2
45
 
3
46
  * Fix a bug where requiring `form/active_model/validations` in a non-Rails environment wouldn't load all necessary files.
@@ -12,7 +55,7 @@
12
55
 
13
56
  # 0.1.3
14
57
 
15
- * Introduce a railtie to load either `ActiveModel::Validations` *or* `Dry::Validations`. This can be controller via `config.reform.validations = :dry`.
58
+ * Introduce a railtie to load either `ActiveModel::Validations` *or* `Dry::Validations`. This can be controlled via `config.reform.validations = :dry`.
16
59
 
17
60
  # 0.1.2
18
61
 
data/Gemfile CHANGED
@@ -1,6 +1,33 @@
1
- source 'https://rubygems.org'
1
+ git_source(:github) do |repo_name|
2
+ repo_name = "#{repo_name}/#{repo_name}" unless repo_name.include?("/")
3
+ "https://github.com/#{repo_name}.git"
4
+ end
2
5
 
3
- # Specify your gem's dependencies in reform-rails.gemspec
6
+ source "https://rubygems.org"
4
7
  gemspec
5
8
 
6
- gem "reform", path: "../reform"
9
+ # gem 'pry-byebug'
10
+ gem "minitest-line"
11
+
12
+ case ENV["GEMS_SOURCE"]
13
+ when "local"
14
+ gem "reform", path: "../reform"
15
+ when "github"
16
+ gem "reform", github: "trailblazer/reform"
17
+ end
18
+
19
+ rails_version = ENV.fetch("RAILS_VERSION", "6.0.0")
20
+
21
+ # bored of wrestling with rails...
22
+
23
+ gem("mongoid", "< 7.0") unless rails_version.to_i >= 6
24
+
25
+
26
+ gem "activerecord", "~> #{rails_version}"
27
+ gem "railties", "~> #{rails_version}"
28
+ if rails_version.to_i >= 6
29
+ gem "sqlite3", "~> 1.4"
30
+ else
31
+ gem "sqlite3", "~> 1.3", "< 1.4"
32
+ end
33
+ puts "Rails version #{rails_version}"
data/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Nick Sutterer
3
+ Copyright (c) 2015-2021 Nick Sutterer
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -14,7 +14,7 @@ Simply don't include this gem if you don't want to use the conventional Reform/R
14
14
 
15
15
  ## Documentation
16
16
 
17
- The [full documentation](http://trailblazer.to/gems/reform/#reform-rails) can be found on the Trailblazer page.
17
+ The [full documentation](https://trailblazer.to/2.0/gems/reform/rails.html) can be found on the Trailblazer page.
18
18
 
19
19
  ## Installation
20
20
 
@@ -24,7 +24,16 @@ Add this line to your application's Gemfile:
24
24
  gem 'reform-rails'
25
25
  ```
26
26
 
27
- Reform-rails needs Reform >= 2.2.
27
+ Reform-rails needs Reform >= 2.3.
28
+
29
+ ## Contributing
30
+
31
+ By default your tests will run against rails 6.0.1.
32
+ Please ensure that you test your changes against all supported ruby and rails versions (see .travis.yml)
33
+
34
+ You can run tests for a specific version of rails by running the following:
35
+
36
+ `export RAILS_VERSION=5.0.0; bundle update; bundle exec rake test`
28
37
 
29
38
  ## License
30
39
 
data/Rakefile CHANGED
@@ -4,7 +4,9 @@ require "rake/testtask"
4
4
  Rake::TestTask.new(:test) do |t|
5
5
  t.libs << "test"
6
6
  t.libs << "lib"
7
- t.test_files = FileList['test/**/*_test.rb']
7
+ t.test_files = FileList['test/*_test.rb']
8
+ t.warning = false
9
+ t.verbose = true
8
10
  end
9
11
 
10
12
  task :default => :test
@@ -1,4 +1,5 @@
1
- require "reform/form/active_model"
2
1
  require "reform/form/orm"
2
+ require "reform/form/active_model"
3
3
  require "reform/form/active_record"
4
4
  require "reform/form/active_model/model_reflections" # only load this in AR context as simple_form currently is bound to AR.
5
+ require "reform/form/active_model/result"
@@ -0,0 +1,15 @@
1
+ class Reform::Contract::Result
2
+ private
3
+
4
+ def filter_for(method, *args)
5
+ @results.collect { |r| r.public_send(method, *args).to_h }
6
+ .inject({}) { |hah, err| hah.merge(err) { |key, old_v, new_v| (new_v.is_a?(Array) ? (old_v |= new_v) : old_v.merge(new_v)) } }
7
+ .find_all { |k, v| # filter :nested=>{:something=>["too nested!"]} #DISCUSS: do we want that here?
8
+ if v.is_a?(Hash)
9
+ nested_errors = v.select { |attr_key, val| attr_key.is_a?(Integer) && val.is_a?(Array) && val.any? }
10
+ v = nested_errors.to_a if nested_errors.any?
11
+ end
12
+ v.is_a?(Array) || v.class.to_s == "ActiveModel::DeprecationHandlingMessageArray"
13
+ }.to_h
14
+ end
15
+ end
@@ -2,114 +2,242 @@ require "active_model"
2
2
  require "reform/form/active_model"
3
3
  require "uber/delegates"
4
4
 
5
- module Reform::Form::ActiveModel
5
+ module Reform
6
+ module Form::ActiveModel
6
7
  # AM::Validations for your form.
7
8
  # Provides ::validates, ::validate, #validate, and #valid?.
8
9
  #
9
10
  # Most of this file contains unnecessary wiring to make ActiveModel's error message magic work.
10
11
  # Since Rails still thinks it's a good idea to do things like object.class.human_attribute_name,
11
12
  # we have some hacks in here to provide that. If it doesn't work for you, don't blame us.
12
- module Validations
13
- def self.included(includer)
14
- includer.instance_eval do
15
- include Reform::Form::ActiveModel
16
-
17
- class << self
18
- extend Uber::Delegates
19
- # # Hooray! Delegate translation back to Reform's Validator class which contains AM::Validations.
20
- delegates :active_model_really_sucks, :human_attribute_name, :lookup_ancestors, :i18n_scope # Rails 3.1.
13
+ module Validations
14
+ def self.included(includer)
15
+ includer.instance_eval do
16
+ include Reform::Form::ActiveModel
17
+
18
+ class << self
19
+ extend Uber::Delegates
20
+ # # Hooray! Delegate translation back to Reform's Validator class which contains AM::Validations.
21
+ delegates :active_model_really_sucks, :human_attribute_name, :lookup_ancestors, :i18n_scope # Rails 3.1.
22
+
23
+ def validation_group_class
24
+ Group
25
+ end
21
26
 
22
- def validation_group_class
23
- Group
27
+ # this is to allow calls like Form::human_attribute_name (note that this is on the CLASS level) to be resolved.
28
+ # those calls happen when adding errors in a custom validation method, which is defined on the form (as an instance method).
29
+ def active_model_really_sucks
30
+ Class.new(Validator).tap do |v|
31
+ v.model_name = model_name
32
+ end
33
+ end
24
34
  end
35
+ end # ::included
36
+ end
25
37
 
26
- # this is to allow calls like Form::human_attribute_name (note that this is on the CLASS level) to be resolved.
27
- # those calls happen when adding errors in a custom validation method, which is defined on the form (as an instance method).
28
- def active_model_really_sucks
29
- Class.new(Validator).tap do |v|
30
- v.model_name = model_name
31
- end
38
+ # The concept of "composition" has still not arrived in Rails core and they rely on 400 methods being
39
+ # available in one object. This is why we need to provide parts of the I18N API in the form.
40
+ def read_attribute_for_validation(name)
41
+ send(name)
42
+ end
43
+
44
+ def initialize(*)
45
+ super
46
+ @amv_errors = ActiveModel::Errors.new(self)
47
+ end
48
+
49
+ # Problem with this method is, it's being used in two completely different contexts: Once to add errors in validations,
50
+ # and second to expose errors for presentation.
51
+ def errors(*args)
52
+ @amv_errors
53
+ end
54
+
55
+ def custom_errors
56
+ # required to keep update the ActiveModel::Errors#details used to test for
57
+ # added errors ActiveModel::Errors#added? and needs to be inside this block!
58
+ super.each do |custom_error|
59
+ errors = custom_error.errors
60
+ # CustomError build always the errors with an hash where the value is an array
61
+ errors.values.first.each do |value|
62
+ @amv_errors.add(errors.keys.first, value)
32
63
  end
33
64
  end
34
- end # ::included
35
- end
65
+ end
36
66
 
37
- def build_errors
38
- Errors.new(self)
39
- end
67
+ def validate!(params, pointers=[])
68
+ @amv_errors = ActiveModel::Errors.new(self)
40
69
 
41
- # The concept of "composition" has still not arrived in Rails core and they rely on 400 methods being
42
- # available in one object. This is why we need to provide parts of the I18N API in the form.
43
- def read_attribute_for_validation(name)
44
- send(name)
45
- end
70
+ super.tap do
71
+ # @fran: super ugly hack thanks to the shit architecture of AMV. let's drop it in 3.0 and move on!
72
+ all_errors = @result.to_results
73
+ nested_errors = @result.instance_variable_get(:@failure)
46
74
 
47
- class Group
48
- def initialize(*)
49
- @validations = Class.new(Reform::Form::ActiveModel::Validations::Validator)
75
+ @result = Reform::Contract::Result.new(all_errors, [nested_errors].compact)
76
+
77
+ @amv_errors = Result::ResultErrors.new(@result, self, @result.success?, @amv_errors)
78
+ end
79
+ @result
50
80
  end
51
81
 
52
- extend Uber::Delegates
53
- delegates :@validations, :validates, :validate, :validates_with, :validate_with
82
+ class Group
83
+ def initialize(*)
84
+ @validations = Class.new(Reform::Form::ActiveModel::Validations::Validator)
85
+ end
86
+
87
+ extend Uber::Delegates
88
+ delegates :@validations, :validates, :validate, :validates_with, :validate_with, :validates_each
54
89
 
55
- def call(fields, errors, form) # FIXME.
56
- validator = @validations.new(form)
57
- validator.valid?
90
+ def call(form)
91
+ validator = @validations.new(form)
92
+ validator.instance_variable_set(:@errors, form.errors)
93
+ success = validator.valid? # run the validations.
58
94
 
59
- validator.errors.each do |name, error| # TODO: handle with proper merge, or something. validator.errors is ALWAYS AM::Errors.
60
- errors.add(name, error)
95
+ Result.new(success, validator.errors.messages)
61
96
  end
62
97
  end
63
- end
64
98
 
65
- # Validator is the validatable object. On the class level, we define validations,
66
- # on instance, it exposes #valid?.
67
- require "delegate"
68
- class Validator < SimpleDelegator
69
- # current i18n scope: :activemodel.
70
- include ActiveModel::Validations
99
+ # The idea here to mimic Dry.RB's Result API.
100
+ class Result < Hash # FIXME; should this be AMV::Errors?
101
+ def initialize(success, hash)
102
+ super()
103
+ @success = success
104
+ hash.each { |k,v| self[k] = v }
105
+ end
71
106
 
72
- class << self
73
- def model_name
74
- @_active_model_sucks ||= ActiveModel::Name.new(Reform::Form, nil, "Reform::Form")
107
+ def success?
108
+ @success
75
109
  end
76
110
 
77
- def model_name=(name)
78
- @_active_model_sucks = name
111
+ def failure?
112
+ ! success?
79
113
  end
80
114
 
81
- def validates(*args, &block)
82
- super(*Declarative::DeepDup.(args), &block)
115
+ def messages
116
+ self
83
117
  end
84
118
 
85
- # Prevent AM:V from mutating the validator class
86
- def attr_reader(*)
119
+ # DISCUSS @FRAN: not sure this is 100% compatible with AMV::Errors?
120
+ def errors
121
+ self
87
122
  end
88
123
 
89
- def attr_writer(*)
124
+ class ResultErrors < ::Reform::Contract::Result::Errors # to expose via #errors. i hate it.
125
+ def initialize(a, b, success, amv_errors)
126
+ super(a, b)
127
+ @success = success
128
+ @amv_errors = amv_errors
129
+ end
130
+
131
+ def empty?
132
+ @success
133
+ end
134
+
135
+ def [](k)
136
+ super(k.to_sym) || []
137
+ end
138
+
139
+ # rails expects this to return a stringified hash of the messages
140
+ def to_s
141
+ messages.to_s
142
+ end
143
+
144
+ def add(key, error_text, **error_options)
145
+ # use rails magic to get the correct error_text and make sure we still update details and fields
146
+ error = @amv_errors.add(key, error_text, **error_options)
147
+ error = [error.message] unless error.is_a?(Array)
148
+
149
+ # using error_text instead of text to either keep the symbol which will be
150
+ # magically replaced with the translate or directly the string - this is also
151
+ # required otherwise in the custom_errors method we will add the actual message in the
152
+ # ActiveModel::Errors#details which is not correct if a symbol was passed here
153
+ Reform::Contract::CustomError.new(key, error_text, @result.to_results)
154
+
155
+ # but since messages method is actually already defined in `Reform::Contract::Result::Errors
156
+ # we need to update the @dotted_errors instance variable to add or merge a new error
157
+ @dotted_errors.key?(key) ? @dotted_errors[key] |= error : @dotted_errors[key] = error
158
+ instance_variable_set(:@dotted_errors, @dotted_errors)
159
+ end
160
+
161
+ def method_missing(m, *args, &block)
162
+ @amv_errors.send(m, *args, &block) # send all methods to the AMV errors, even privates.
163
+ end
164
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
165
+
166
+ def respond_to?(method, include_all = false)
167
+ @amv_errors.respond_to?(method, include_all) ? true : super
168
+ end
169
+
170
+ def full_messages
171
+ base_errors = @amv_errors.full_messages
172
+ form_fields = @amv_errors.instance_variable_get(:@base).instance_variable_get(:@fields)
173
+ nested_errors = full_messages_for_nested_fields(form_fields)
174
+
175
+ [base_errors, nested_errors].flatten.compact
176
+ end
177
+
178
+ private
179
+
180
+ def full_messages_for_nested_fields(form_fields)
181
+ form_fields.map { |field| full_messages_for_twin(field[1]) }
182
+ end
183
+
184
+ def full_messages_for_twin(object)
185
+ return get_collection_errors(object) if object.is_a? Disposable::Twin::Collection
186
+ return get_amv_errors(object) if object.is_a? Disposable::Twin
187
+
188
+ nil
189
+ end
190
+
191
+ def get_collection_errors(twin_collection)
192
+ twin_collection.map { |twin| get_amv_errors(twin) }
193
+ end
194
+
195
+ def get_amv_errors(object)
196
+ object.instance_variable_get(:@amv_errors).full_messages
197
+ end
90
198
  end
91
199
  end
92
200
 
93
- def initialize(form)
94
- super(form)
95
- self.class.model_name = form.model_name # one of the many reasons why i will drop support for AM::V in 2.1. or maybe a bit later.
96
- end
201
+ # Validator is the validatable object. On the class level, we define validations,
202
+ # on instance, it exposes #valid?.
203
+ require "delegate"
204
+ class Validator < SimpleDelegator
205
+ # current i18n scope: :activemodel.
206
+ include ActiveModel::Validations
207
+
208
+ class << self
209
+ def model_name
210
+ @_active_model_sucks ||= ActiveModel::Name.new(Reform::Form, nil, "Reform::Form")
211
+ end
212
+
213
+ def model_name=(name)
214
+ @_active_model_sucks = name
215
+ end
216
+
217
+ def validates(*args, &block)
218
+ super(*Declarative::DeepDup.(args), &block)
219
+ end
97
220
 
98
- # FIXME: for some weird reason, Object#format is reserved and form.send(:format) crashes with ArgumentError: too few arguments.
99
- # method_missing fix doesn't work with ruby 2.0 or 2.3
221
+ # Prevent AM:V from mutating the validator class
222
+ def attr_reader(*)
223
+ end
224
+
225
+ def attr_writer(*)
226
+ end
227
+ end
100
228
 
101
- # this fixes 2.0 but I'm guessing that their are more methods than just format to consider
102
- # def format
103
- # __getobj__.format
104
- # end
229
+ def initialize(form)
230
+ super(form)
231
+ self.class.model_name = form.model_name
232
+ end
105
233
 
106
- def method_missing(m, *args, &block)
107
- __getobj__.send(m, *args, &block) # send all methods to the form, even privates.
234
+ def method_missing(m, *args, &block)
235
+ __getobj__.send(m, *args, &block) # send all methods to the form, even privates.
236
+ end
237
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
108
238
  end
109
239
  end
110
- end
111
240
 
112
- class Errors < ActiveModel::Errors
113
- include Reform::Form::Errors::Merge
241
+
114
242
  end
115
243
  end
@@ -1,13 +1,14 @@
1
- require "uber/delegates"
2
-
3
1
  module Reform::Form::ActiveModel
4
2
  def self.included(base)
5
3
  base.class_eval do
6
4
  extend ClassMethods
7
5
  register_feature ActiveModel
8
6
 
9
- extend Uber::Delegates
10
- delegates :model, *[:persisted?, :to_key, :to_param, :id] # Uber::Delegates
7
+ delegations = Module.new do
8
+ delegate :persisted?, :to_key, :to_param, :id, to: :model
9
+ end
10
+
11
+ include delegations # now, those methods (e.g. {#persisted?}) can be overridden by another module.
11
12
 
12
13
  def to_model # this is called somewhere in FormBuilder and ActionController.
13
14
  self
@@ -42,15 +43,19 @@ module Reform::Form::ActiveModel
42
43
 
43
44
  # moved from reform as not applicable to dry
44
45
  def validates(*args, &block)
45
- validation(:default, inherit: true) { validates *args, &block }
46
+ validation(name: :default, inherit: true) { validates *args, &block }
46
47
  end
47
48
 
48
49
  def validate(*args, &block)
49
- validation(:default, inherit: true) { validate *args, &block }
50
+ validation(name: :default, inherit: true) { validate *args, &block }
50
51
  end
51
52
 
52
53
  def validates_with(*args, &block)
53
- validation(:default, inherit: true) { validates_with *args, &block }
54
+ validation(name: :default, inherit: true) { validates_with *args, &block }
55
+ end
56
+
57
+ def validates_each(*args, &block)
58
+ validation(name: :default, inherit: true) { validates_each *args, &block }
54
59
  end
55
60
 
56
61
  # Set a model name for this form if the infered is wrong.
@@ -85,7 +90,6 @@ module Reform::Form::ActiveModel
85
90
 
86
91
  private
87
92
  def active_model_name_for(string, namespace=nil)
88
- return ::ActiveModel::Name.new(OpenStruct.new(:name => string)) if ::ActiveModel::VERSION::MAJOR == 3 and ::ActiveModel::VERSION::MINOR == 0 # TODO: remove when we drop rails 3.x.
89
93
  ::ActiveModel::Name.new(self, namespace, string)
90
94
  end
91
95
  end # ClassMethods
@@ -1,5 +1,3 @@
1
- require "reform/form/orm"
2
-
3
1
  module Reform::Form::ActiveRecord
4
2
  def self.included(base)
5
3
  base.class_eval do
@@ -0,0 +1,26 @@
1
+ gem 'mongoid', ">= 4.0"
2
+
3
+ module Reform::Form::Mongoid
4
+ def self.included(base)
5
+ base.class_eval do
6
+ register_feature Reform::Form::Mongoid
7
+ include Reform::Form::ActiveModel
8
+ include Reform::Form::ORM
9
+ extend ClassMethods
10
+ end
11
+ end
12
+
13
+ module ClassMethods
14
+ def validates_uniqueness_of(attribute, options={})
15
+ options = options.merge(:attributes => [attribute])
16
+ validates_with(UniquenessValidator, options)
17
+ end
18
+ def i18n_scope
19
+ :mongoid
20
+ end
21
+ end
22
+
23
+ UniquenessValidator = Class.new("::Mongoid::Validatable::UniquenessValidator".constantize) do
24
+ include Reform::Form::ORM::UniquenessValidator
25
+ end
26
+ end
@@ -19,7 +19,11 @@ module Reform::Form::MultiParameterAttributes
19
19
  )
20
20
  end
21
21
  end
22
- params.merge!(date_attributes)
22
+
23
+ date_attributes.each do |attribute, date|
24
+ params[attribute] = date
25
+ end
26
+ params
23
27
  end
24
28
 
25
29
  private
@@ -19,7 +19,10 @@ module Reform::Form::ORM
19
19
 
20
20
  @klass = record.class # this is usually done in the super-sucky #setup method.
21
21
  super(record).tap do |res|
22
- form.errors.add(property, record.errors.first.last) if record.errors.present?
22
+ if record.errors.present?
23
+ error = self.class.name.include?("Mongoid") ? record.errors.first.last : :taken
24
+ form.errors.add(property, error)
25
+ end
23
26
  end
24
27
  end
25
28
  end
@@ -7,6 +7,12 @@
7
7
  # validates :title, unique: true
8
8
  #
9
9
  # == Options
10
+ #
11
+ # = Case Sensitivity
12
+ # Case sensitivity is true by default, but can be set to false:
13
+ #
14
+ # validates :title, unique: { case_sensitive: false }
15
+ #
10
16
  # = Scope
11
17
  # A scope can be use to filter the records that need to be compare with the
12
18
  # current value to validate. A scope array can have one to many fields define.
@@ -31,9 +37,19 @@
31
37
  class Reform::Form::UniqueValidator < ActiveModel::EachValidator
32
38
  def validate_each(form, attribute, value)
33
39
  model = form.model_for_property(attribute)
40
+ original_attribute = form.options_for(attribute)[:private_name]
34
41
 
35
42
  # search for models with attribute equals to form field value
36
- query = model.class.where(attribute => value)
43
+ query = if options[:case_sensitive] == false && value
44
+ model.class.where("lower(#{original_attribute}) = ?", value.downcase)
45
+ else
46
+ model.class.where(original_attribute => value)
47
+ end
48
+
49
+ # if model persisted, query should bypass model
50
+ if model.persisted?
51
+ query = query.where("#{model.class.primary_key} != ?", model.id)
52
+ end
37
53
 
38
54
  # apply scope if options has been declared
39
55
  Array(options[:scope]).each do |field|
@@ -41,9 +57,7 @@ class Reform::Form::UniqueValidator < ActiveModel::EachValidator
41
57
  query = query.where(field => form.send(field))
42
58
  end
43
59
 
44
- # if model persisted, query may return 0 or 1 rows, else 0
45
- allow_count = model.persisted? ? 1 : 0
46
- form.errors.add(attribute, :taken) if query.count > allow_count
60
+ form.errors.add(attribute, :taken) if query.count > 0
47
61
  end
48
62
  end
49
63
 
@@ -0,0 +1,4 @@
1
+ require 'reform/form/orm'
2
+ require 'reform/form/active_model'
3
+ require 'reform/form/mongoid'
4
+ require 'reform/form/active_model/model_reflections' # only load this in AR context as simple_form currently is bound to AR.
@@ -6,48 +6,53 @@ module Reform
6
6
  initializer "reform.form_extensions", after: :load_config_initializers do
7
7
  validations = config.reform.validations || :active_model
8
8
 
9
+ require "reform/form/multi_parameter_attributes"
10
+
9
11
  if validations == :active_model
10
12
  active_model!
11
13
  elsif validations == :dry
12
- dry!
14
+ enable_form_builder_methods = config.reform.enable_active_model_builder_methods || false
15
+
16
+ dry!(enable_form_builder_methods)
13
17
  else
14
18
  warn "[Reform::Rails] No validation backend set. Please do so via `config.reform.validations = :active_model`."
15
19
  end
16
20
  end
17
21
 
18
22
  def active_model!
19
- require "reform"
20
- require "reform/form/active_model/model_validations"
21
23
  require "reform/form/active_model/form_builder_methods"
22
24
  require "reform/form/active_model"
25
+
26
+ require "reform/form/active_model/model_validations"
23
27
  require "reform/form/active_model/validations"
24
- require "reform/form/multi_parameter_attributes"
25
28
 
26
- require "reform/active_record" if defined?(ActiveRecord)
27
- require "reform/mongoid" if defined?(Mongoid)
29
+ require "reform/active_record" if defined?(::ActiveRecord)
30
+ require "reform/mongoid" if defined?(::Mongoid)
28
31
 
29
32
  Reform::Form.class_eval do
30
33
  include Reform::Form::ActiveModel
31
34
  include Reform::Form::ActiveModel::FormBuilderMethods
32
- include Reform::Form::ActiveRecord if defined?(ActiveRecord)
33
- include Reform::Form::Mongoid if defined?(Mongoid)
35
+ include Reform::Form::ActiveRecord if defined?(::ActiveRecord)
36
+ include Reform::Form::Mongoid if defined?(::Mongoid)
34
37
  include Reform::Form::ActiveModel::Validations
35
38
  end
36
39
  end
37
40
 
38
- def dry!
39
- require "reform"
40
- require "reform/form/dry"
41
+ def dry!(enable_am = true)
42
+ if enable_am
43
+ require "reform/form/active_model/form_builder_methods" # this is for simple_form, etc.
41
44
 
42
- require "reform/form/multi_parameter_attributes"
43
- require "reform/form/active_model/form_builder_methods" # this is for simple_form, etc.
45
+ # This adds Form#persisted? and all the other crap #form_for depends on. Grrrr.
46
+ require "reform/form/active_model" # DISCUSS: only when using simple_form.
47
+ end
44
48
 
45
- # This adds Form#persisted? and all the other crap #form_for depends on. Grrrr.
46
- require "reform/form/active_model" # DISCUSS: only when using simple_form.
49
+ require "reform/form/dry"
47
50
 
48
51
  Reform::Form.class_eval do
49
- include Reform::Form::ActiveModel # DISCUSS: only when using simple_form.
50
- include Reform::Form::ActiveModel::FormBuilderMethods
52
+ if enable_am
53
+ include Reform::Form::ActiveModel
54
+ include Reform::Form::ActiveModel::FormBuilderMethods
55
+ end
51
56
 
52
57
  include Reform::Form::Dry
53
58
  end
@@ -1,5 +1,5 @@
1
1
  module Reform
2
2
  module Rails
3
- VERSION = "0.1.7"
3
+ VERSION = "0.2.6"
4
4
  end
5
5
  end
data/lib/reform/rails.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "reform/rails/version"
2
+ require 'reform'
2
3
  require "reform/rails/railtie"
3
4
 
4
5
  module Reform
data/reform-rails.gemspec CHANGED
@@ -14,19 +14,12 @@ Gem::Specification.new do |spec|
14
14
  spec.homepage = "https://github.com/trailblazer/reform-rails"
15
15
  spec.license = "MIT"
16
16
 
17
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test/|spec/|features/|database.sqlite3)})
19
+ end
18
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
21
  spec.require_paths = ["lib"]
20
22
 
21
- spec.add_dependency "reform", ">= 2.2.0"
22
- spec.add_dependency "activemodel", ">= 3.2"
23
-
24
- spec.add_development_dependency "rails"
25
- spec.add_development_dependency "bundler"
26
- spec.add_development_dependency "rake"
27
- spec.add_development_dependency "minitest"
28
- spec.add_development_dependency "actionpack"
29
- spec.add_development_dependency "activerecord"
30
- spec.add_development_dependency "mongoid"
31
- spec.add_development_dependency "sqlite3"
23
+ spec.add_dependency "reform", ">= 2.3.1", "< 3.0.0"
24
+ spec.add_dependency "activemodel", ">= 5.0"
32
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reform-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nick Sutterer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-26 00:00:00.000000000 Z
11
+ date: 2023-08-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: reform
@@ -16,140 +16,34 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.2.0
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ">="
25
- - !ruby/object:Gem::Version
26
- version: 2.2.0
27
- - !ruby/object:Gem::Dependency
28
- name: activemodel
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
19
+ version: 2.3.1
20
+ - - "<"
32
21
  - !ruby/object:Gem::Version
33
- version: '3.2'
22
+ version: 3.0.0
34
23
  type: :runtime
35
24
  prerelease: false
36
25
  version_requirements: !ruby/object:Gem::Requirement
37
26
  requirements:
38
27
  - - ">="
39
28
  - !ruby/object:Gem::Version
40
- version: '3.2'
41
- - !ruby/object:Gem::Dependency
42
- name: rails
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: minitest
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
29
+ version: 2.3.1
30
+ - - "<"
88
31
  - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
32
+ version: 3.0.0
97
33
  - !ruby/object:Gem::Dependency
98
- name: actionpack
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: activerecord
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: mongoid
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: sqlite3
34
+ name: activemodel
141
35
  requirement: !ruby/object:Gem::Requirement
142
36
  requirements:
143
37
  - - ">="
144
38
  - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
39
+ version: '5.0'
40
+ type: :runtime
147
41
  prerelease: false
148
42
  version_requirements: !ruby/object:Gem::Requirement
149
43
  requirements:
150
44
  - - ">="
151
45
  - !ruby/object:Gem::Version
152
- version: '0'
46
+ version: '5.0'
153
47
  description: Automatically load and include all common Reform features for a standard
154
48
  Rails environment.
155
49
  email:
@@ -158,32 +52,29 @@ executables: []
158
52
  extensions: []
159
53
  extra_rdoc_files: []
160
54
  files:
55
+ - ".github/workflows/ci.yml"
161
56
  - ".gitignore"
162
- - ".travis.yml"
163
57
  - CHANGES.md
164
58
  - Gemfile
165
59
  - LICENSE.txt
166
60
  - README.md
167
61
  - Rakefile
168
- - database.sqlite3
169
- - gemfiles/Gemfile.rails-3.2
170
- - gemfiles/Gemfile.rails-4.0
171
- - gemfiles/Gemfile.rails-4.1
172
- - gemfiles/Gemfile.rails-4.2
173
62
  - lib/reform/active_record.rb
174
63
  - lib/reform/form/active_model.rb
175
64
  - lib/reform/form/active_model/form_builder_methods.rb
176
65
  - lib/reform/form/active_model/model_reflections.rb
177
66
  - lib/reform/form/active_model/model_validations.rb
67
+ - lib/reform/form/active_model/result.rb
178
68
  - lib/reform/form/active_model/validations.rb
179
69
  - lib/reform/form/active_record.rb
70
+ - lib/reform/form/mongoid.rb
180
71
  - lib/reform/form/multi_parameter_attributes.rb
181
72
  - lib/reform/form/orm.rb
182
73
  - lib/reform/form/validation/unique_validator.rb
74
+ - lib/reform/mongoid.rb
183
75
  - lib/reform/rails.rb
184
76
  - lib/reform/rails/railtie.rb
185
77
  - lib/reform/rails/version.rb
186
- - log/development.log
187
78
  - reform-rails.gemspec
188
79
  homepage: https://github.com/trailblazer/reform-rails
189
80
  licenses:
@@ -204,8 +95,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
204
95
  - !ruby/object:Gem::Version
205
96
  version: '0'
206
97
  requirements: []
207
- rubyforge_project:
208
- rubygems_version: 2.5.1
98
+ rubygems_version: 3.2.3
209
99
  signing_key:
210
100
  specification_version: 4
211
101
  summary: Automatically load and include all common Rails form features.
data/.travis.yml DELETED
@@ -1,18 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
-
4
- rvm:
5
- - 2.3.1
6
- - 2.2.3
7
- - 2.0.0
8
- services:
9
- - mongodb
10
- gemfile:
11
- - gemfiles/Gemfile.rails-4.2
12
- - gemfiles/Gemfile.rails-4.1
13
- - gemfiles/Gemfile.rails-4.0
14
- - gemfiles/Gemfile.rails-3.2
15
- # - gemfiles/Gemfile.rails-3.1
16
- # - gemfiles/Gemfile.rails-3.0
17
- matrix:
18
- fast_finish: true
data/database.sqlite3 DELETED
Binary file
@@ -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.2.0'
7
- gem 'activerecord', '~> 3.2.0'
@@ -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', '~> 4.0.0'
7
- gem 'activerecord', '~> 4.0.0'
@@ -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', '~> 4.1.0'
7
- gem 'activerecord', '~> 4.1.0'
@@ -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', '~> 4.2.0'
7
- gem 'activerecord', '~> 4.2.0'
data/log/development.log DELETED
File without changes