trans_forms 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/README.md +3 -2
- data/lib/trans_forms/form_base.rb +44 -5
- data/lib/trans_forms/main_model/proxy.rb +92 -1
- data/lib/trans_forms/main_model.rb +64 -7
- data/lib/trans_forms/version.rb +1 -1
- data/lib/trans_forms.rb +0 -1
- data/spec/spec_helper.rb +5 -2
- data/spec/support/schema.rb +12 -12
- data/spec/support/trans_forms/main_model_forms.rb +11 -2
- data/spec/trans_forms/form_base_spec.rb +19 -7
- data/spec/trans_forms/main_model/proxy_spec.rb +14 -1
- data/spec/trans_forms/main_model_spec.rb +46 -14
- metadata +23 -103
- data/.gitignore +0 -3
- data/.rspec +0 -2
- data/.travis.yml +0 -5
- data/Gemfile +0 -4
- data/LICENSE +0 -22
- data/Rakefile +0 -27
- data/lib/trans_forms/form_errors.rb +0 -38
- data/spec/trans_forms/form_errors_spec.rb +0 -14
- data/trans_forms.gemspec +0 -29
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
MDQxZWY0NTJkNWQ5NWIyNTkyOTBjYjhlNmViMjUwZDI5NzkwOTcwZA==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 816031429c4c367af9bfee0e344f49bd11432fef
|
4
|
+
data.tar.gz: 326b77fa9d791c60808b71a57c2386b60b0a6041
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
ZWE3MjgwNTA3Y2Q3OTM5OGExMmU3Y2Q1Yzk2NzNiODI0MTg1YTY3ODUzOTVj
|
11
|
-
NTBhYjQ2YmRkNWFkNWFjNWVmMGFlMWZjYTMxYWRmMjkzMTk4YWQ=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NDE0NzQ4YTY2MmVkZmZjZWUwNGU2NzE3ZGJiY2M0ZTdmMmRhZWM5NDFhMWI4
|
14
|
-
NDM1ODUxZTFmY2VjNGU0YWJlODQ0MjQ5ZThiOGNlZmZhODA0MGMwNmM5ZjVl
|
15
|
-
Mzc5MTBmNWQzNWNmNjQ4ODY3MTk4YmU2YTFjYzlkMDAyNTNlYzY=
|
6
|
+
metadata.gz: e94173975503abd86f039254b66bbcc4c5e1868b8a67226fd72db4b053184115862d7656679cce2e9f9732445e69a516ddd88f5686fa0937226fb82b03703e4f
|
7
|
+
data.tar.gz: 7b2aee4f0f4f06bbb0f1e064592164135fed78d46b5f91447175718e6733e59908ad02350b31b03aaec843f1e1edb54012f9dfa2a121b223768477eb251e9518
|
data/README.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
# TransForms
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/trans_forms.svg)](http://badge.fury.io/rb/trans_forms)
|
1
3
|
[![Build Status](https://travis-ci.org/dannemanne/trans_forms.svg?branch=master)](https://travis-ci.org/dannemanne/trans_forms)
|
2
4
|
[![Code Climate](https://codeclimate.com/github/dannemanne/trans_forms.png)](https://codeclimate.com/github/dannemanne/trans_forms)
|
3
|
-
|
4
|
-
# TransForms
|
5
|
+
[![Test Coverage](https://codeclimate.com/github/dannemanne/trans_forms/coverage.png)](https://codeclimate.com/github/dannemanne/trans_forms)
|
5
6
|
|
6
7
|
TransForms is short for Transactional Forms. I created it mainly because I felt that
|
7
8
|
the ActiveRecord Models all to often get cluttered with a lot of conditional validations
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'virtus'
|
2
|
-
|
3
|
-
|
4
|
-
require 'rails/all'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_model'
|
5
4
|
|
6
5
|
module TransForms
|
7
6
|
class FormBase
|
@@ -14,16 +13,22 @@ module TransForms
|
|
14
13
|
|
15
14
|
include TransForms::Callbacks
|
16
15
|
|
16
|
+
attr_accessor :_last_error
|
17
|
+
|
17
18
|
def save
|
18
19
|
valid? && run_transaction
|
19
20
|
end
|
20
21
|
|
21
22
|
def save!
|
22
|
-
|
23
|
+
valid? || raise(ActiveRecord::RecordInvalid.new(self))
|
24
|
+
save || (_last_error && raise(_last_error) || raise(ActiveRecord::RecordNotSaved))
|
23
25
|
end
|
24
26
|
|
25
|
-
# ActiveModel support
|
27
|
+
# ActiveModel support.
|
28
|
+
# Note that these methods will be overwritten if the +proxy+ option
|
29
|
+
# is enabled in the call to +set_main_model+
|
26
30
|
def persisted?; false end
|
31
|
+
def new_record?; !persisted? end
|
27
32
|
def to_key; nil end
|
28
33
|
|
29
34
|
protected
|
@@ -40,8 +45,42 @@ module TransForms
|
|
40
45
|
rescue ActiveRecord::ActiveRecordError => e
|
41
46
|
# Triggers callback
|
42
47
|
after_save_on_error_callback e
|
48
|
+
self._last_error = e
|
49
|
+
if e.respond_to?(:record)
|
50
|
+
e.record.errors.each do |attribute, message|
|
51
|
+
errors.add(attribute, message)
|
52
|
+
end
|
53
|
+
end
|
43
54
|
false
|
44
55
|
end
|
45
56
|
|
57
|
+
# A method to to use when you want to redirect any errors raised to a
|
58
|
+
# specific attribute. It requires a block and any ActiveRecordErrors
|
59
|
+
# that are raised within this block will be assigned to the Form Models
|
60
|
+
# Errors instance for the key specified by +attr+.
|
61
|
+
#
|
62
|
+
# class ArticleCreator < ApplicationTransForm
|
63
|
+
# attribute :author_name
|
64
|
+
# ...
|
65
|
+
#
|
66
|
+
# transaction do
|
67
|
+
# all_errors_to(:author_name) do
|
68
|
+
# # If this following statement raises an ActiveRecordError, then
|
69
|
+
# # that error message will be stored on the attribute :author_name
|
70
|
+
# Author.create!(name: author_name)
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# ...
|
74
|
+
# end
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
def all_errors_to(attr)
|
78
|
+
raise 'No block given' unless block_given?
|
79
|
+
yield
|
80
|
+
rescue ActiveRecord::ActiveRecordError => e
|
81
|
+
errors[attr] = e.message
|
82
|
+
raise e
|
83
|
+
end
|
84
|
+
|
46
85
|
end
|
47
86
|
end
|
@@ -7,7 +7,98 @@ module TransForms
|
|
7
7
|
# and controllers handle the form model as if it were
|
8
8
|
# the main model itself
|
9
9
|
|
10
|
+
# Dependency for the Proxy Module. Usually this is already
|
11
|
+
# included before Proxy is included, but we make sure it
|
12
|
+
# is present by including it from here as well.
|
13
|
+
include ::TransForms::MainModel::Active
|
14
|
+
|
15
|
+
def persisted?
|
16
|
+
respond_to?(:main_instance) && main_instance && main_instance.persisted?
|
17
|
+
end
|
18
|
+
|
19
|
+
# In case the Main Model has implemented custom +to_param+ method, we need
|
20
|
+
# to make sure we use it here as well
|
21
|
+
def to_param
|
22
|
+
respond_to?(:main_instance) && main_instance && main_instance.to_param || super
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns an Enumerable of all key attributes of the main instanceif any is
|
26
|
+
# set, regardless if the object is persisted or not. Returns +nil+ if there
|
27
|
+
# is no main_instance or if main_instance have no key attributes.
|
28
|
+
#
|
29
|
+
# class UserForm < TransForms::BaseForm
|
30
|
+
# set_main_model :user, proxy: true
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# form = UserForm.new
|
34
|
+
# form.to_key # => nil
|
35
|
+
#
|
36
|
+
# form.user = User.new
|
37
|
+
# form.to_key # => nil
|
38
|
+
#
|
39
|
+
# form.user.save # => true
|
40
|
+
# form.to_key # => [1]
|
41
|
+
def to_key
|
42
|
+
respond_to?(:main_instance) && main_instance && main_instance.to_key
|
43
|
+
end
|
44
|
+
|
10
45
|
module ClassMethods
|
46
|
+
RESERVED_COLUMN_NAMES = %w(id created_at updated_at)
|
47
|
+
REJECT_COLUMN_PROC = Proc.new { |c| RESERVED_COLUMN_NAMES.include?(c.name) }
|
48
|
+
|
49
|
+
# Configures the proxy setup. Called from +set_main_model+ when
|
50
|
+
# the option :proxy was supplied. +proxy_options+ will be the value
|
51
|
+
# for that :proxy key.
|
52
|
+
#
|
53
|
+
# If +proxy
|
54
|
+
def configure_proxy(proxy_options)
|
55
|
+
if proxy_options.is_a?(Hash)
|
56
|
+
set_proxy_attributes proxy_options[:attributes] if proxy_options[:attributes]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# If +attributes+ is the Boolean value TRUE then we will proxy all
|
61
|
+
# of the attributes from the main_model class except for a few
|
62
|
+
# reserved attributes.
|
63
|
+
#
|
64
|
+
# But if +attributes+ is an array then we only proxy those attributes
|
65
|
+
# listed in the array. If any of the attributes listed in the array is
|
66
|
+
# not an actual attribute of the main model then an Error will be
|
67
|
+
# raised.
|
68
|
+
def set_proxy_attributes(attributes)
|
69
|
+
if attributes == :all
|
70
|
+
proxy_columns main_class.columns.reject(&REJECT_COLUMN_PROC)
|
71
|
+
elsif attributes.is_a?(Array)
|
72
|
+
attr_names = attributes.map(&:to_s)
|
73
|
+
proxy_columns main_class.columns.reject(&REJECT_COLUMN_PROC).select { |c| attr_names.include?(c.name) }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Given a set of ActiveRecord Columns, will setup attributes according
|
78
|
+
# to the Virtus standard that will have the default value of the main
|
79
|
+
# instance record.
|
80
|
+
def proxy_columns(columns)
|
81
|
+
columns.each do |column|
|
82
|
+
if (type = column_type(column.type)).present?
|
83
|
+
# When setting the default value, note that +main_instance+ might be nil, so we have to use +try+
|
84
|
+
attribute column.name, type, default: proc { |f| f.main_instance.try(column.name) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Returns a Class for the specific column type.
|
90
|
+
def column_type(type)
|
91
|
+
case type
|
92
|
+
when :integer then Integer
|
93
|
+
when :float, :decimal then Float
|
94
|
+
when :string, :text, :uuid then String
|
95
|
+
when :datetime, :timestamp, :time then DateTime
|
96
|
+
when :date then Date
|
97
|
+
when :boolean then Virtus::Attribute::Boolean # Boolean is not a standard Ruby class
|
98
|
+
else
|
99
|
+
raise "Could not match column type '#{type}' for #{model_name}"
|
100
|
+
end
|
101
|
+
end
|
11
102
|
|
12
103
|
# Returns an ActiveModel::Name object for module. It can be
|
13
104
|
# used to retrieve all kinds of naming-related information
|
@@ -23,7 +114,7 @@ module TransForms
|
|
23
114
|
# PostForm.model_name.plural # => "posts"
|
24
115
|
def model_name
|
25
116
|
@_model_name ||= begin
|
26
|
-
klass = respond_to?(:
|
117
|
+
klass = respond_to?(:main_class) ? main_class : self
|
27
118
|
|
28
119
|
namespace = klass.parents.detect do |n|
|
29
120
|
n.respond_to?(:use_relative_model_naming?) && n.use_relative_model_naming?
|
@@ -6,20 +6,55 @@ module TransForms
|
|
6
6
|
|
7
7
|
# This method will extend the BaseForm functionality with the
|
8
8
|
# TransForms::MainModel::Active module.
|
9
|
+
#
|
10
|
+
# The +model+ argument is a symbol in the underscore format
|
11
|
+
# of a Class name, i.e. +:post+ or +:product_group+
|
12
|
+
#
|
13
|
+
# The +options+ argument is a Hash that can have the following
|
14
|
+
# options set:
|
15
|
+
#
|
16
|
+
# +:proxy+
|
17
|
+
# With proxy defined, the method +model_name+, +to_key+ and
|
18
|
+
# +persisted?+ will refer to the main_model and main_instance
|
19
|
+
# instead of the Form Model.
|
20
|
+
#
|
21
|
+
# class PostForm < TransForms::FormBase
|
22
|
+
# set_main_model :post, proxy: true
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# You can also configure the proxy further by defining the
|
26
|
+
# +attributes+ option inside the proxy. If the value is +:all+
|
27
|
+
# then it will define all the columns of the main model. But
|
28
|
+
# you can also set the value to an array with the names of the
|
29
|
+
# columns you wish to proxy:
|
30
|
+
#
|
31
|
+
# class PostForm < TransForms::FormBase
|
32
|
+
# set_main_model :post, proxy: { attributes: :all }
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# class PostForm < TransForms::FormBase
|
36
|
+
# set_main_model :post, proxy: { attributes: %w(title body status) }
|
37
|
+
# end
|
9
38
|
def set_main_model(model, options = {})
|
10
39
|
include TransForms::MainModel::Active
|
11
40
|
|
12
41
|
# Stores the main_model record in a class_attribute
|
13
|
-
class_attribute :main_model
|
14
42
|
self.main_model = model
|
15
43
|
|
44
|
+
# If model is in namespace then it might be needed to specify manually
|
45
|
+
self._class_name = options[:class_name] if options.has_key?(:class_name)
|
46
|
+
|
16
47
|
# Defines an instance accessor for the main_model
|
17
48
|
attr_accessor model
|
18
49
|
|
19
50
|
# Implements proxy module that overwrites model_name method
|
20
51
|
# to instead return an ActiveModel::Mame class for the
|
21
52
|
# main_model class
|
22
|
-
|
53
|
+
if options[:proxy]
|
54
|
+
include TransForms::MainModel::Proxy
|
55
|
+
|
56
|
+
configure_proxy options[:proxy]
|
57
|
+
end
|
23
58
|
end
|
24
59
|
|
25
60
|
end
|
@@ -34,17 +69,24 @@ module TransForms
|
|
34
69
|
# anyway. If this module is included manually (like in one of the specs) then
|
35
70
|
# it prevents any error to occur.
|
36
71
|
after_save_on_error :assert_record_on_error if respond_to?(:after_save_on_error)
|
72
|
+
|
73
|
+
# Adding class attributes to store model and options for each usage.
|
74
|
+
class_attribute :main_model, :_class_name
|
37
75
|
end
|
38
76
|
|
39
|
-
#
|
40
|
-
# models involved in the form transation.
|
77
|
+
# Instance method to retrieve the current main model instance
|
41
78
|
def main_instance
|
42
79
|
send main_model
|
43
80
|
end
|
44
81
|
|
45
82
|
# Combines the errors from the FormModel as well as the main model instances
|
46
83
|
def errors
|
47
|
-
@errors ||=
|
84
|
+
@errors ||= ActiveModel::Errors.new(self)
|
85
|
+
if respond_to?(:main_instance) && main_instance && main_instance.errors.any?
|
86
|
+
main_instance.errors
|
87
|
+
else
|
88
|
+
@errors
|
89
|
+
end
|
48
90
|
end
|
49
91
|
|
50
92
|
# In it's default implementation, this method will look at the class name
|
@@ -80,7 +122,7 @@ module TransForms
|
|
80
122
|
end
|
81
123
|
end
|
82
124
|
|
83
|
-
|
125
|
+
protected
|
84
126
|
|
85
127
|
# This method is assigned to the after_save_on_error callback
|
86
128
|
#
|
@@ -104,10 +146,25 @@ module TransForms
|
|
104
146
|
if record.class.model_name.is_a?(ActiveModel::Name)
|
105
147
|
record.class.model_name.element
|
106
148
|
else
|
107
|
-
record.class.model_name.
|
149
|
+
record.class.model_name.param_key
|
108
150
|
end
|
109
151
|
end
|
110
152
|
|
153
|
+
|
154
|
+
module ClassMethods
|
155
|
+
|
156
|
+
# Returns the class of the main_model
|
157
|
+
def main_class
|
158
|
+
@main_class ||=
|
159
|
+
if _class_name.present?
|
160
|
+
_class_name.constantize
|
161
|
+
else
|
162
|
+
main_model.to_s.classify.constantize
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
|
111
168
|
end
|
112
169
|
end
|
113
170
|
end
|
data/lib/trans_forms/version.rb
CHANGED
data/lib/trans_forms.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter '/spec/'
|
4
|
+
end
|
5
|
+
|
1
6
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
7
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
8
|
# Require this file using `require "spec_helper"` to ensure that it is only
|
@@ -7,7 +12,6 @@
|
|
7
12
|
|
8
13
|
require 'bundler/setup'
|
9
14
|
require 'trans_forms'
|
10
|
-
require 'rails/version'
|
11
15
|
require 'support/schema'
|
12
16
|
require 'support/models'
|
13
17
|
require 'database_cleaner'
|
@@ -17,7 +21,6 @@ Dir[File.expand_path('../support/trans_forms/*.rb', __FILE__)].each { |f| requir
|
|
17
21
|
I18n.enforce_available_locales = false
|
18
22
|
|
19
23
|
RSpec.configure do |config|
|
20
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
21
24
|
config.run_all_when_everything_filtered = true
|
22
25
|
config.filter_run :focus
|
23
26
|
|
data/spec/support/schema.rb
CHANGED
@@ -6,18 +6,18 @@ ActiveRecord::Base.establish_connection({
|
|
6
6
|
})
|
7
7
|
|
8
8
|
# prepare test data
|
9
|
-
|
10
|
-
|
11
|
-
create_table "users", :force => true do |t|
|
12
|
-
t.string "name"
|
13
|
-
t.integer "age"
|
14
|
-
end
|
9
|
+
ActiveRecord::Schema.define do
|
10
|
+
self.verbose = false
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
create_table "users", :force => true do |t|
|
13
|
+
t.string "name"
|
14
|
+
t.integer "age"
|
15
|
+
t.datetime "created_at", :null => false
|
16
|
+
t.datetime "updated_at", :null => false
|
20
17
|
end
|
21
|
-
end
|
22
18
|
|
23
|
-
|
19
|
+
create_table "phone_numbers", :force => true do |t|
|
20
|
+
t.integer "user_id"
|
21
|
+
t.string "number"
|
22
|
+
end
|
23
|
+
end
|
@@ -3,9 +3,8 @@ class MainModelModel
|
|
3
3
|
end
|
4
4
|
|
5
5
|
class ProxyModel
|
6
|
-
class_attribute :main_model
|
7
|
-
self.main_model = :user
|
8
6
|
include TransForms::MainModel::Proxy
|
7
|
+
self.main_model = :user
|
9
8
|
end
|
10
9
|
|
11
10
|
class UserUpdater < TransForms::FormBase
|
@@ -25,3 +24,13 @@ end
|
|
25
24
|
class UserProxyModel < TransForms::FormBase
|
26
25
|
set_main_model :user, proxy: true
|
27
26
|
end
|
27
|
+
|
28
|
+
class UserProxyAllModel < TransForms::FormBase
|
29
|
+
ATTR_ARG = :all
|
30
|
+
set_main_model :user, proxy: { attributes: ATTR_ARG }
|
31
|
+
end
|
32
|
+
|
33
|
+
class UserProxySelectModel < TransForms::FormBase
|
34
|
+
ATTR_ARG = %w(name)
|
35
|
+
set_main_model :user, proxy: { attributes: ATTR_ARG }
|
36
|
+
end
|
@@ -10,7 +10,7 @@ module TransForms
|
|
10
10
|
|
11
11
|
expect(form.name).to eq(attr[:name])
|
12
12
|
expect(form.age).to eq(attr[:age])
|
13
|
-
expect { form.foo }.to raise_error
|
13
|
+
expect { form.foo }.to raise_error(NoMethodError)
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -26,14 +26,26 @@ module TransForms
|
|
26
26
|
end
|
27
27
|
|
28
28
|
describe '#save' do
|
29
|
-
|
30
|
-
form
|
31
|
-
expect(form.save).to be true
|
29
|
+
context 'when no errors occur inside +transaction+ block' do
|
30
|
+
let(:form) { NoErrorInTransactionForm.new }
|
31
|
+
it { expect( form.save ).to be true }
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
form
|
36
|
-
expect(form.save).to be false
|
34
|
+
context 'when errors do occur inside the +transaction+ block' do
|
35
|
+
let(:form) { ErrorInTransactionForm.new }
|
36
|
+
it { expect( form.save ).to be false }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#save!' do
|
41
|
+
context 'when no errors occur inside +transaction+ block' do
|
42
|
+
let(:form) { NoErrorInTransactionForm.new }
|
43
|
+
it { expect( form.save! ).to be true }
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when active errors do occur inside the +transaction+ block' do
|
47
|
+
let(:form) { ErrorInTransactionForm.new }
|
48
|
+
it { expect { form.save! }.to raise_error(ActiveRecord::ActiveRecordError) }
|
37
49
|
end
|
38
50
|
end
|
39
51
|
|
@@ -7,7 +7,20 @@ module TransForms
|
|
7
7
|
it 'returns an ActiveModel::Name instance for the main_model instead of form model' do
|
8
8
|
expect(ProxyModel.main_model).to eq :user
|
9
9
|
expect(ProxyModel.name).to eq 'ProxyModel'
|
10
|
-
expect(ProxyModel.model_name
|
10
|
+
expect(ProxyModel.model_name).to eq 'User'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'column_type' do
|
15
|
+
it 'returns a Class representing the type of an ActiveRecord Column' do
|
16
|
+
expect(ProxyModel.column_type(:integer)).to eq Integer
|
17
|
+
expect(ProxyModel.column_type(:string)).to eq String
|
18
|
+
expect(ProxyModel.column_type(:text)).to eq String
|
19
|
+
expect(ProxyModel.column_type(:datetime)).to eq DateTime
|
20
|
+
expect(ProxyModel.column_type(:date)).to eq Date
|
21
|
+
expect(ProxyModel.column_type(:float)).to eq Float
|
22
|
+
expect(ProxyModel.column_type(:decimal)).to eq Float
|
23
|
+
expect(ProxyModel.column_type(:boolean)).to eq Virtus::Attribute::Boolean
|
11
24
|
end
|
12
25
|
end
|
13
26
|
end
|
@@ -8,8 +8,8 @@ module TransForms
|
|
8
8
|
describe 'set_main_model' do
|
9
9
|
it 'defines accessor attributes for main model and stores them in a class attribute' do
|
10
10
|
form = MainModelModel.new
|
11
|
-
expect{ form.user }.to raise_error
|
12
|
-
expect{ form.user = User.new }.to raise_error
|
11
|
+
expect{ form.user }.to raise_error(NoMethodError)
|
12
|
+
expect{ form.user = User.new }.to raise_error(NoMethodError)
|
13
13
|
|
14
14
|
MainModelModel.set_main_model :user
|
15
15
|
form = MainModelModel.new
|
@@ -18,10 +18,49 @@ module TransForms
|
|
18
18
|
|
19
19
|
expect(MainModelModel.main_model).to eq :user
|
20
20
|
end
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
|
22
|
+
describe 'option[:proxy]' do
|
23
|
+
it 'proxies +model_name+ method to the main_model' do
|
24
|
+
expect(UserProxyModel.main_model).to eq :user
|
25
|
+
expect(UserProxyModel.name).to eq 'UserProxyModel'
|
26
|
+
expect(UserProxyModel.model_name).to eq 'User'
|
27
|
+
end
|
28
|
+
it 'proxies +persisted?+ method to the main_instance' do
|
29
|
+
form = UserProxyModel.new(user: User.new)
|
30
|
+
expect(form.user.persisted?).to be false
|
31
|
+
expect(form.persisted?).to be false
|
32
|
+
|
33
|
+
form.user = User.create!(name: 'John Doe')
|
34
|
+
expect(form.user.persisted?).to be true
|
35
|
+
expect(form.persisted?).to be true
|
36
|
+
end
|
37
|
+
it 'proxies +to_key+ method to the main_instance' do
|
38
|
+
form = UserProxyModel.new(user: User.new)
|
39
|
+
expect(form.user.to_key).to be nil
|
40
|
+
expect(form.to_key).to be nil
|
41
|
+
|
42
|
+
form.user = User.create!(name: 'John Doe')
|
43
|
+
expect(form.user.to_key).not_to be nil
|
44
|
+
expect(form.to_key).to eq form.user.to_key
|
45
|
+
end
|
46
|
+
it 'defines attributes for all non-reserved column names of the main model' do
|
47
|
+
# ATTR_ARG is defined in test model, just to make
|
48
|
+
# sure we test with a correct model.
|
49
|
+
expect(UserProxyAllModel::ATTR_ARG).to eq :all
|
50
|
+
expect(UserProxyAllModel.main_class).to eq User
|
51
|
+
expect(UserProxyAllModel.attribute_set.each.map(&:name).map(&:to_s)).to eq User.columns.reject { |c| %w(id created_at updated_at).include?(c.name) }.map(&:name)
|
52
|
+
end
|
53
|
+
it 'defines attributes for the specified columns' do
|
54
|
+
# ATTR_ARG is defined in test model, just to make
|
55
|
+
# sure we test with a correct model.
|
56
|
+
expect(UserProxySelectModel::ATTR_ARG).to eq %w(name)
|
57
|
+
expect(UserProxySelectModel.main_class).to eq User
|
58
|
+
expect(UserProxySelectModel.attribute_set.each.map(&:name).map(&:to_s)).to eq %w(name)
|
59
|
+
end
|
60
|
+
it 'sets the default value of an attribute to the corresponding attribute of the main instance' do
|
61
|
+
form = UserProxyAllModel.new(model: user)
|
62
|
+
expect(form.name).to eq user.name
|
63
|
+
end
|
25
64
|
end
|
26
65
|
end
|
27
66
|
|
@@ -34,14 +73,7 @@ module TransForms
|
|
34
73
|
|
35
74
|
it 'raises an error if the model supplied is not the type of main model' do
|
36
75
|
expect(UserUpdater.main_model).to eq :user
|
37
|
-
expect { UserUpdater.new(model: phone_number) }.to raise_error
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
describe 'model_name' do
|
42
|
-
it 'does not raise an error when raised' do
|
43
|
-
#TODO: Improve this spec
|
44
|
-
expect { UserUpdater.model_name }.not_to raise_error
|
76
|
+
expect { UserUpdater.new(model: phone_number) }.to raise_error(TransForms::NotImplementedError)
|
45
77
|
end
|
46
78
|
end
|
47
79
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trans_forms
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel Viklund
|
@@ -10,118 +10,48 @@ bindir: bin
|
|
10
10
|
cert_chain: []
|
11
11
|
date: 2014-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: rake
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ! '>='
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ! '>='
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rspec
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ! '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '2'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ! '>='
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '2'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec-rails
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ! '>='
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '2'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ! '>='
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '2'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: sqlite3
|
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: database_cleaner
|
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
13
|
- !ruby/object:Gem::Dependency
|
84
14
|
name: virtus
|
85
15
|
requirement: !ruby/object:Gem::Requirement
|
86
16
|
requirements:
|
87
|
-
- -
|
17
|
+
- - ">="
|
88
18
|
- !ruby/object:Gem::Version
|
89
19
|
version: '0'
|
90
20
|
type: :runtime
|
91
21
|
prerelease: false
|
92
22
|
version_requirements: !ruby/object:Gem::Requirement
|
93
23
|
requirements:
|
94
|
-
- -
|
24
|
+
- - ">="
|
95
25
|
- !ruby/object:Gem::Version
|
96
26
|
version: '0'
|
97
27
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
28
|
+
name: activemodel
|
99
29
|
requirement: !ruby/object:Gem::Requirement
|
100
30
|
requirements:
|
101
|
-
- -
|
31
|
+
- - ">="
|
102
32
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
33
|
+
version: 3.1.0
|
104
34
|
type: :runtime
|
105
35
|
prerelease: false
|
106
36
|
version_requirements: !ruby/object:Gem::Requirement
|
107
37
|
requirements:
|
108
|
-
- -
|
38
|
+
- - ">="
|
109
39
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
40
|
+
version: 3.1.0
|
111
41
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
42
|
+
name: activesupport
|
113
43
|
requirement: !ruby/object:Gem::Requirement
|
114
44
|
requirements:
|
115
|
-
- -
|
45
|
+
- - ">="
|
116
46
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
47
|
+
version: 3.1.0
|
118
48
|
type: :runtime
|
119
49
|
prerelease: false
|
120
50
|
version_requirements: !ruby/object:Gem::Requirement
|
121
51
|
requirements:
|
122
|
-
- -
|
52
|
+
- - ">="
|
123
53
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
54
|
+
version: 3.1.0
|
125
55
|
description: Gem to create Form records that handles multiple changes wrapped in a
|
126
56
|
transaction
|
127
57
|
email:
|
@@ -130,13 +60,7 @@ executables: []
|
|
130
60
|
extensions: []
|
131
61
|
extra_rdoc_files: []
|
132
62
|
files:
|
133
|
-
- .gitignore
|
134
|
-
- .rspec
|
135
|
-
- .travis.yml
|
136
|
-
- Gemfile
|
137
|
-
- LICENSE
|
138
63
|
- README.md
|
139
|
-
- Rakefile
|
140
64
|
- lib/generators/rails/setup_generator.rb
|
141
65
|
- lib/generators/rails/templates/application_trans_form.rb
|
142
66
|
- lib/generators/rails/templates/trans_form.rb
|
@@ -149,7 +73,6 @@ files:
|
|
149
73
|
- lib/trans_forms/callbacks.rb
|
150
74
|
- lib/trans_forms/errors.rb
|
151
75
|
- lib/trans_forms/form_base.rb
|
152
|
-
- lib/trans_forms/form_errors.rb
|
153
76
|
- lib/trans_forms/main_model.rb
|
154
77
|
- lib/trans_forms/main_model/proxy.rb
|
155
78
|
- lib/trans_forms/nested_forms.rb
|
@@ -166,11 +89,9 @@ files:
|
|
166
89
|
- spec/support/trans_forms/user_creator_1.rb
|
167
90
|
- spec/trans_forms/callbacks_spec.rb
|
168
91
|
- spec/trans_forms/form_base_spec.rb
|
169
|
-
- spec/trans_forms/form_errors_spec.rb
|
170
92
|
- spec/trans_forms/main_model/proxy_spec.rb
|
171
93
|
- spec/trans_forms/main_model_spec.rb
|
172
94
|
- spec/trans_forms/nested_forms_spec.rb
|
173
|
-
- trans_forms.gemspec
|
174
95
|
homepage: https://github.com/dannemanne/trans_forms
|
175
96
|
licenses:
|
176
97
|
- MIT
|
@@ -181,34 +102,33 @@ require_paths:
|
|
181
102
|
- lib
|
182
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
183
104
|
requirements:
|
184
|
-
- -
|
105
|
+
- - ">="
|
185
106
|
- !ruby/object:Gem::Version
|
186
|
-
version:
|
107
|
+
version: 1.9.3
|
187
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
109
|
requirements:
|
189
|
-
- -
|
110
|
+
- - ">="
|
190
111
|
- !ruby/object:Gem::Version
|
191
112
|
version: '0'
|
192
113
|
requirements: []
|
193
114
|
rubyforge_project:
|
194
|
-
rubygems_version: 2.2.2
|
115
|
+
rubygems_version: 2.5.2.2
|
195
116
|
signing_key:
|
196
117
|
specification_version: 4
|
197
118
|
summary: Gem to create Form records that handles multiple changes wrapped in a transaction
|
198
119
|
test_files:
|
199
|
-
- spec/generators/trans_form/trans_form_generator_spec.rb
|
200
120
|
- spec/spec_helper.rb
|
201
|
-
- spec/support/models.rb
|
202
121
|
- spec/support/schema.rb
|
203
|
-
- spec/support/trans_forms/callback_forms.rb
|
204
122
|
- spec/support/trans_forms/main_model_forms.rb
|
205
123
|
- spec/support/trans_forms/multiple_records_forms.rb
|
206
124
|
- spec/support/trans_forms/nested_forms.rb
|
125
|
+
- spec/support/trans_forms/callback_forms.rb
|
207
126
|
- spec/support/trans_forms/simple_forms.rb
|
208
127
|
- spec/support/trans_forms/user_creator_1.rb
|
209
|
-
- spec/
|
210
|
-
- spec/
|
211
|
-
- spec/trans_forms/form_errors_spec.rb
|
212
|
-
- spec/trans_forms/main_model/proxy_spec.rb
|
128
|
+
- spec/support/models.rb
|
129
|
+
- spec/generators/trans_form/trans_form_generator_spec.rb
|
213
130
|
- spec/trans_forms/main_model_spec.rb
|
131
|
+
- spec/trans_forms/main_model/proxy_spec.rb
|
132
|
+
- spec/trans_forms/callbacks_spec.rb
|
214
133
|
- spec/trans_forms/nested_forms_spec.rb
|
134
|
+
- spec/trans_forms/form_base_spec.rb
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/LICENSE
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
Copyright (c) 2014 Daniel Viklund
|
2
|
-
|
3
|
-
MIT License
|
4
|
-
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
-
a copy of this software and associated documentation files (the
|
7
|
-
"Software"), to deal in the Software without restriction, including
|
8
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
-
permit persons to whom the Software is furnished to do so, subject to
|
11
|
-
the following conditions:
|
12
|
-
|
13
|
-
The above copyright notice and this permission notice shall be
|
14
|
-
included in all copies or substantial portions of the Software.
|
15
|
-
|
16
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'rake'
|
2
|
-
require 'bundler/gem_tasks'
|
3
|
-
require 'rspec/core/rake_task'
|
4
|
-
|
5
|
-
task 'default' => 'ci'
|
6
|
-
|
7
|
-
desc 'Run all tests for CI'
|
8
|
-
task 'ci' => 'spec'
|
9
|
-
|
10
|
-
desc 'Run all specs'
|
11
|
-
task 'spec' => 'spec:all'
|
12
|
-
|
13
|
-
namespace 'spec' do
|
14
|
-
task 'all' => ['trans_forms', 'generators']
|
15
|
-
|
16
|
-
def spec_task(name)
|
17
|
-
desc "Run #{name} specs"
|
18
|
-
RSpec::Core::RakeTask.new(name) do |t|
|
19
|
-
t.pattern = "spec/#{name}/**/*_spec.rb"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
spec_task 'trans_forms'
|
24
|
-
spec_task 'generators'
|
25
|
-
|
26
|
-
end
|
27
|
-
|
@@ -1,38 +0,0 @@
|
|
1
|
-
module TransForms
|
2
|
-
class FormErrors
|
3
|
-
attr_accessor :form_model, :original
|
4
|
-
|
5
|
-
def initialize(form_model, original)
|
6
|
-
self.form_model, self.original = form_model, original
|
7
|
-
end
|
8
|
-
|
9
|
-
def error_models
|
10
|
-
[original, form_model.main_instance.try(:errors)].compact
|
11
|
-
end
|
12
|
-
|
13
|
-
def full_messages
|
14
|
-
original.full_messages
|
15
|
-
end
|
16
|
-
|
17
|
-
def clear
|
18
|
-
error_models.each do |em|
|
19
|
-
em.clear
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def [](key)
|
24
|
-
error_models.inject([]) { |acc, error_model|
|
25
|
-
acc += (error_model[key])
|
26
|
-
}
|
27
|
-
end
|
28
|
-
|
29
|
-
def empty?
|
30
|
-
error_models.all?(&:empty?)
|
31
|
-
end
|
32
|
-
|
33
|
-
def method_missing(m, *args, &block)
|
34
|
-
original.send(m, *args, &block)
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module TransForms
|
4
|
-
describe FormErrors do
|
5
|
-
describe '#error_models' do
|
6
|
-
it 'does not raise an error when called on a form model without a main_instance' do
|
7
|
-
form = UserUpdater.new
|
8
|
-
expect(form.main_model).to eq(:user)
|
9
|
-
expect(form.main_instance).to be nil
|
10
|
-
expect { form.errors.error_models }.not_to raise_error
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
data/trans_forms.gemspec
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
require File.expand_path('../lib/trans_forms/version', __FILE__)
|
2
|
-
|
3
|
-
Gem::Specification.new do |s|
|
4
|
-
s.authors = ['Daniel Viklund']
|
5
|
-
s.email = ['dannemanne@gmail.com']
|
6
|
-
s.summary = 'Gem to create Form records that handles multiple changes wrapped in a transaction'
|
7
|
-
s.description = 'Gem to create Form records that handles multiple changes wrapped in a transaction'
|
8
|
-
s.homepage = 'https://github.com/dannemanne/trans_forms'
|
9
|
-
s.license = 'MIT'
|
10
|
-
|
11
|
-
s.name = 'trans_forms'
|
12
|
-
s.version = TransForms::VERSION
|
13
|
-
s.date = '2014-07-08'
|
14
|
-
|
15
|
-
s.files = `git ls-files`.split("\n")
|
16
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
-
s.require_paths = ['lib']
|
19
|
-
|
20
|
-
s.add_development_dependency 'rake'
|
21
|
-
s.add_development_dependency 'rspec', '>= 2'
|
22
|
-
s.add_development_dependency 'rspec-rails', '>= 2'
|
23
|
-
s.add_development_dependency 'sqlite3'
|
24
|
-
s.add_development_dependency 'database_cleaner'
|
25
|
-
|
26
|
-
s.add_dependency 'virtus'
|
27
|
-
s.add_dependency 'rails', '>= 3'
|
28
|
-
s.add_dependency 'activemodel', '>= 3'
|
29
|
-
end
|