rom-rails 0.2.1 → 0.3.0.beta1
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 +4 -4
- data/.rubocop.yml +26 -0
- data/CHANGELOG.md +17 -0
- data/README.md +4 -0
- data/lib/generators/rom/commands/templates/create.rb.erb +10 -0
- data/lib/generators/rom/commands/templates/delete.rb.erb +7 -0
- data/lib/generators/rom/commands/templates/update.rb.erb +10 -0
- data/lib/generators/rom/commands_generator.rb +33 -5
- data/lib/generators/rom/form/templates/edit_form.rb.erb +24 -0
- data/lib/generators/rom/form/templates/new_form.rb.erb +24 -0
- data/lib/generators/rom/form_generator.rb +39 -0
- data/lib/generators/rom/mapper/templates/mapper.rb.erb +9 -11
- data/lib/generators/rom/mapper_generator.rb +11 -1
- data/lib/generators/rom/relation/templates/relation.rb.erb +3 -2
- data/lib/generators/rom/relation_generator.rb +16 -1
- data/lib/rom-rails.rb +0 -5
- data/lib/rom/model.rb +7 -90
- data/lib/rom/rails/active_record/configuration.rb +105 -0
- data/lib/rom/rails/configuration.rb +4 -27
- data/lib/rom/rails/model/form.rb +59 -0
- data/lib/rom/rails/model/form/dsl.rb +173 -0
- data/lib/rom/rails/model/params.rb +72 -0
- data/lib/rom/rails/model/validator.rb +74 -0
- data/lib/rom/rails/model/validator/uniqueness_validator.rb +39 -0
- data/lib/rom/rails/railtie.rb +65 -29
- data/lib/rom/rails/version.rb +1 -1
- data/rom-rails.gemspec +3 -1
- data/spec/dummy/app/commands/tasks.rb +5 -0
- data/spec/dummy/app/commands/users.rb +4 -10
- data/spec/dummy/app/controllers/users_controller.rb +30 -0
- data/spec/dummy/app/forms/new_user_form.rb +9 -0
- data/spec/dummy/app/forms/update_user_form.rb +9 -0
- data/spec/dummy/app/forms/user_form.rb +15 -0
- data/spec/dummy/app/mappers/users.rb +6 -6
- data/spec/dummy/app/relations/tasks.rb +9 -0
- data/spec/dummy/app/relations/users.rb +5 -1
- data/spec/dummy/app/views/users/edit.html.erb +6 -0
- data/spec/dummy/app/views/users/new.html.erb +6 -0
- data/spec/dummy/config/routes.rb +5 -1
- data/spec/dummy/db/migrate/20141110205016_add_users.rb +2 -0
- data/spec/dummy/db/migrate/20150202194440_create_tasks.rb +7 -0
- data/spec/dummy/db/schema.rb +8 -8
- data/spec/dummy/spec/features/users_spec.rb +30 -0
- data/spec/dummy/spec/integration/logger_spec.rb +1 -1
- data/spec/dummy/spec/integration/user_commands_spec.rb +2 -18
- data/spec/dummy/spec/integration/user_model_mapping_spec.rb +2 -2
- data/spec/dummy/spec/integration/user_params_spec.rb +30 -15
- data/spec/lib/active_record/configuration_spec.rb +98 -0
- data/spec/lib/generators/commands_generator_spec.rb +54 -14
- data/spec/lib/generators/form_generator_spec.rb +89 -0
- data/spec/lib/generators/mapper_generator_spec.rb +10 -12
- data/spec/lib/generators/relation_generator_spec.rb +16 -6
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/form_spec.rb +297 -0
- data/spec/unit/{model_spec.rb → params_spec.rb} +0 -0
- data/spec/unit/validator_spec.rb +75 -0
- metadata +72 -20
- data/lib/generators/rom/commands/templates/commands.rb.erb +0 -15
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/params/user_params.rb +0 -7
- data/spec/dummy/app/validators/user_validator.rb +0 -3
@@ -14,19 +14,17 @@ describe ROM::Generators::MapperGenerator do
|
|
14
14
|
expect(destination_root).to have_structure {
|
15
15
|
directory 'app' do
|
16
16
|
directory 'mappers' do
|
17
|
-
file '
|
17
|
+
file 'user_mapper.rb' do
|
18
18
|
contains <<-CONTENT.strip_heredoc
|
19
|
-
ROM
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
29
|
-
|
19
|
+
class UserMapper < ROM::Mapper
|
20
|
+
# relation :users
|
21
|
+
#
|
22
|
+
# specify model and attributes ie
|
23
|
+
#
|
24
|
+
# model User
|
25
|
+
#
|
26
|
+
# attribute :name
|
27
|
+
# attribute :email
|
30
28
|
end
|
31
29
|
CONTENT
|
32
30
|
end
|
@@ -2,27 +2,30 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
require 'generators/rom/relation_generator'
|
4
4
|
|
5
|
-
describe ROM::Generators::RelationGenerator do
|
5
|
+
describe ROM::Generators::RelationGenerator, type: :generator do
|
6
6
|
destination File.expand_path('../../../../tmp', __FILE__)
|
7
7
|
|
8
|
-
before(:
|
8
|
+
before(:each) do
|
9
9
|
prepare_destination
|
10
|
-
run_generator ['users']
|
11
10
|
end
|
12
11
|
|
13
12
|
specify do
|
13
|
+
run_generator ['users']
|
14
|
+
default_adapter = ROM.adapters.keys.first
|
15
|
+
|
14
16
|
expect(destination_root).to have_structure {
|
15
17
|
directory 'app' do
|
16
18
|
directory 'relations' do
|
17
|
-
file '
|
19
|
+
file 'users_relation.rb' do
|
18
20
|
contains <<-CONTENT.strip_heredoc
|
19
|
-
ROM
|
21
|
+
class UsersRelation < ROM::Relation[:#{default_adapter}]
|
22
|
+
dataset :users
|
23
|
+
|
20
24
|
# define your methods here ie:
|
21
25
|
#
|
22
26
|
# def all
|
23
27
|
# select(:id, :name).order(:id)
|
24
28
|
# end
|
25
|
-
#
|
26
29
|
end
|
27
30
|
CONTENT
|
28
31
|
end
|
@@ -30,4 +33,11 @@ describe ROM::Generators::RelationGenerator do
|
|
30
33
|
end
|
31
34
|
}
|
32
35
|
end
|
36
|
+
|
37
|
+
specify "with given adapter" do
|
38
|
+
run_generator ['users', '--adapter=memory']
|
39
|
+
|
40
|
+
relation = File.read(File.join(destination_root, 'app', 'relations', 'users_relation.rb'))
|
41
|
+
expect(relation).to include("class UsersRelation < ROM::Relation[:memory]")
|
42
|
+
end
|
33
43
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,297 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Form' do
|
4
|
+
subject(:form) do
|
5
|
+
Class.new(ROM::Model::Form) do
|
6
|
+
def self.name
|
7
|
+
'UserForm'
|
8
|
+
end
|
9
|
+
|
10
|
+
input do
|
11
|
+
set_model_name 'User'
|
12
|
+
|
13
|
+
attribute :email, String
|
14
|
+
end
|
15
|
+
|
16
|
+
validations do
|
17
|
+
validates :email, presence: true
|
18
|
+
end
|
19
|
+
|
20
|
+
def commit!(*args)
|
21
|
+
"it works #{args.inspect}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '.build' do
|
27
|
+
it 'rejects blank strings from params' do
|
28
|
+
input = {
|
29
|
+
'name' => 'Jane',
|
30
|
+
'hash' => { 'one' => '', 'two' => 2 },
|
31
|
+
'array' => [{ 'three' => '', 'four' => 4 }, 5]
|
32
|
+
}
|
33
|
+
|
34
|
+
form_object = form.build(input)
|
35
|
+
|
36
|
+
expect(form_object.params).to eql(
|
37
|
+
name: 'Jane', hash: { two: 2 }, array: [{ four: 4 }, 5]
|
38
|
+
)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '.commands' do
|
43
|
+
it 'builds its own command registry' do
|
44
|
+
form = Class.new(ROM::Model::Form) {
|
45
|
+
inject_commands_for :tasks
|
46
|
+
commands users: :create
|
47
|
+
input { attribute :name }
|
48
|
+
validations { validates :name, presence: true }
|
49
|
+
|
50
|
+
def commit!
|
51
|
+
users.try { users.create.call(params) }
|
52
|
+
end
|
53
|
+
}
|
54
|
+
|
55
|
+
form_object = form.build(name: '').save
|
56
|
+
|
57
|
+
expect(form_object).not_to be_success
|
58
|
+
expect(form_object.errors[:name]).to include("can't be blank")
|
59
|
+
expect(rom.relations.users.first).to be(nil)
|
60
|
+
|
61
|
+
form_object = form.build(name: 'Jane').save
|
62
|
+
|
63
|
+
expect(form_object).to be_success
|
64
|
+
expect(rom.relations.users.first).to include(name: 'Jane')
|
65
|
+
|
66
|
+
expect(form_object.tasks).to be(rom.command(:tasks))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe '.key' do
|
71
|
+
it 'returns default key' do
|
72
|
+
expect(form.key).to eql([:id])
|
73
|
+
expect(form.new({}, { id: 312 }).to_key).to eql([312])
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'sets a custom composite key' do
|
77
|
+
form = Class.new(ROM::Model::Form) do
|
78
|
+
def self.name
|
79
|
+
'UserForm'
|
80
|
+
end
|
81
|
+
|
82
|
+
key :foo_id, :bar_id
|
83
|
+
|
84
|
+
input do
|
85
|
+
set_model_name 'User'
|
86
|
+
|
87
|
+
attribute :email, String
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
expect(form.key).to eql([:foo_id, :bar_id])
|
92
|
+
expect(form.new({}, { foo_id: 312, bar_id: 132 }).to_key).to eql([312, 132])
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '.model_name' do
|
97
|
+
it 'delegates to Params.model_name' do
|
98
|
+
expect(form.model_name).to be(form.params.model_name)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe 'input DSL' do
|
103
|
+
it 'defines params handler' do
|
104
|
+
expect(form.const_defined?(:Params)).to be(true)
|
105
|
+
expect(form.params.attribute_set.map(&:name)).to eql([:email])
|
106
|
+
expect(form.params.model_name).to eql('User')
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'defines a model' do
|
110
|
+
expect(form.const_defined?(:Model)).to be(true)
|
111
|
+
expect(form.model.attribute_set.map(&:name)).to match_array([:id, :email])
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'raises error when attribute is in conflict with form interface' do
|
115
|
+
expect {
|
116
|
+
Class.new(ROM::Model::Form) do
|
117
|
+
input do
|
118
|
+
attribute :commit!
|
119
|
+
end
|
120
|
+
end
|
121
|
+
}.to raise_error(ArgumentError, /commit! attribute is in conflict/)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe 'validator DSL' do
|
126
|
+
it 'defines validator' do
|
127
|
+
expect(form.const_defined?(:Validator)).to be(true)
|
128
|
+
|
129
|
+
expect(form.validator).not_to be(nil)
|
130
|
+
|
131
|
+
expect { form.validator.call(email: 'jane@doe') }.not_to raise_error
|
132
|
+
|
133
|
+
expect { form.validator.call(email: '') }.to raise_error(
|
134
|
+
ROM::Model::ValidationError
|
135
|
+
)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe '#model_name' do
|
140
|
+
it 'delegates to model' do
|
141
|
+
form_object = form.build
|
142
|
+
expect(form_object.model_name).to be(form_object.model.model_name)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
describe '#persisted?' do
|
147
|
+
it 'delegates to model' do
|
148
|
+
form_object = form.build
|
149
|
+
expect(form_object).not_to be_persisted
|
150
|
+
expect(form_object.persisted?).to be(form_object.model.persisted?)
|
151
|
+
|
152
|
+
form_object = form.build({}, { id: 1 })
|
153
|
+
expect(form_object).to be_persisted
|
154
|
+
expect(form_object.persisted?).to be(form_object.model.persisted?)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
describe '#to_model' do
|
159
|
+
context 'with a new model' do
|
160
|
+
it 'returns model object without key set' do
|
161
|
+
model = form.build(email: 'jane@doe').to_model
|
162
|
+
|
163
|
+
expect(model.id).to be(nil)
|
164
|
+
expect(model.model_name).to eql('User')
|
165
|
+
expect(model.to_key).to eql([])
|
166
|
+
expect(model.to_param).to be(nil)
|
167
|
+
expect(model).not_to be_persisted
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
context 'with a persisted model' do
|
172
|
+
it 'returns model object with key set' do
|
173
|
+
model = form.build({ email: 'jane@doe' }, { id: 312 }).to_model
|
174
|
+
|
175
|
+
expect(model.id).to be(312)
|
176
|
+
expect(model.model_name).to eql('User')
|
177
|
+
expect(model.to_key).to eql([312])
|
178
|
+
expect(model.to_param).to eql('312')
|
179
|
+
expect(model).to be_persisted
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe '#save' do
|
185
|
+
it 'commits the form without extra args' do
|
186
|
+
result = form.build({}).save.result
|
187
|
+
expect(result).to eql('it works []')
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'commits the form with extra args' do
|
191
|
+
result = form.build({}).save(1, 2, 3).result
|
192
|
+
expect(result).to eql('it works [1, 2, 3]')
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
describe "#errors" do
|
197
|
+
context "with a new model" do
|
198
|
+
it "exposes an activemodel compatible error" do
|
199
|
+
errors = form.build({}).errors
|
200
|
+
|
201
|
+
expect(errors).to be_instance_of(
|
202
|
+
ActiveModel::Errors
|
203
|
+
)
|
204
|
+
|
205
|
+
expect(errors[:email]).to eq []
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "#attributes" do
|
211
|
+
it "returns processed attributes" do
|
212
|
+
form = Class.new(ROM::Model::Form) do
|
213
|
+
def self.name
|
214
|
+
'UserForm'
|
215
|
+
end
|
216
|
+
|
217
|
+
key :foo_id, :bar_id
|
218
|
+
|
219
|
+
input do
|
220
|
+
set_model_name 'User'
|
221
|
+
|
222
|
+
attribute :uid, Integer
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
form_object = form.build(uid: "12345")
|
227
|
+
expect(form_object.attributes[:uid]).to eq 12_345
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
describe "#validate!" do
|
232
|
+
it "runs validations and assigns errors" do
|
233
|
+
form_object = form.build({})
|
234
|
+
form_object.validate!
|
235
|
+
|
236
|
+
expect(form_object.errors[:email]).to include "can't be blank"
|
237
|
+
end
|
238
|
+
|
239
|
+
it "uses processed parameters" do
|
240
|
+
form = Class.new(ROM::Model::Form) do
|
241
|
+
def self.name
|
242
|
+
'UserForm'
|
243
|
+
end
|
244
|
+
|
245
|
+
key :foo_id, :bar_id
|
246
|
+
|
247
|
+
input do
|
248
|
+
set_model_name 'User'
|
249
|
+
|
250
|
+
attribute :email, String
|
251
|
+
attribute :country, String, default: "Unkown"
|
252
|
+
end
|
253
|
+
|
254
|
+
validations do
|
255
|
+
validates :email, presence: true
|
256
|
+
validates :country, presence: true
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
form_object = form.build(uid: "12345")
|
261
|
+
form_object.validate!
|
262
|
+
|
263
|
+
expect(form_object.errors[:country]).to be_blank
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
describe 'inheritance' do
|
268
|
+
let(:child_form) do
|
269
|
+
Class.new(form) do
|
270
|
+
def self.name
|
271
|
+
"NewUserForm"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'copies model_name' do
|
277
|
+
expect(child_form.model_name.name).to eql(form.model_name.name)
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'copies input' do
|
281
|
+
expect(child_form.params.attribute_set[:email]).to_not be(nil)
|
282
|
+
expect(child_form.params).to_not be(form.params)
|
283
|
+
end
|
284
|
+
|
285
|
+
it 'copies model' do
|
286
|
+
expect(child_form.model.attribute_set[:email]).to_not be(nil)
|
287
|
+
expect(child_form.model).to_not be(form.model)
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'copies validator' do
|
291
|
+
expect(child_form.validator.validators.first).to be_instance_of(
|
292
|
+
ActiveModel::Validations::PresenceValidator
|
293
|
+
)
|
294
|
+
expect(child_form.validator).to_not be(form.validator)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
File without changes
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Validation' do
|
4
|
+
subject(:validator) { user_validator.new(params) }
|
5
|
+
|
6
|
+
let(:user_params) do
|
7
|
+
Class.new {
|
8
|
+
include ROM::Model::Params
|
9
|
+
|
10
|
+
attribute :name, String
|
11
|
+
attribute :email, String
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:user_validator) do
|
16
|
+
Class.new {
|
17
|
+
include ROM::Model::Validator
|
18
|
+
|
19
|
+
relation :users
|
20
|
+
|
21
|
+
validates :name, presence: true, uniqueness: { message: 'TAKEN!' }
|
22
|
+
validates :email, uniqueness: true
|
23
|
+
|
24
|
+
def self.name
|
25
|
+
'UserValidator'
|
26
|
+
end
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#call' do
|
31
|
+
let(:params) { {} }
|
32
|
+
|
33
|
+
it 'raises validation error when params are not valid' do
|
34
|
+
expect { validator.call }.to raise_error(ROM::Model::ValidationError)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#validate" do
|
39
|
+
let(:params) { {} }
|
40
|
+
|
41
|
+
it "sets errors when params are not valid" do
|
42
|
+
validator.validate
|
43
|
+
expect(validator.errors[:name]).to eql(["can't be blank"])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ':presence' do
|
48
|
+
let(:params) { user_params.new(name: '') }
|
49
|
+
|
50
|
+
it 'sets error messages' do
|
51
|
+
expect(validator).to_not be_valid
|
52
|
+
expect(validator.errors[:name]).to eql(["can't be blank"])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ':uniqueness' do
|
57
|
+
let(:params) { user_params.new(name: 'Jane', email: 'jane@doe.org') }
|
58
|
+
|
59
|
+
before do
|
60
|
+
rom.relations.users.insert(name: 'Jane', email: 'jane@doe.org')
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'sets default error messages' do
|
64
|
+
expect(validator).to_not be_valid
|
65
|
+
expect(validator.errors[:email]).to eql(['has already been taken'])
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'sets custom error messages' do
|
69
|
+
rom.relations.users.insert(name: 'Jane', email: 'jane@doe.org')
|
70
|
+
|
71
|
+
expect(validator).to_not be_valid
|
72
|
+
expect(validator.errors[:name]).to eql(['TAKEN!'])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|