rom-rails 0.3.0.beta1 → 0.3.0.rc1

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.
@@ -7,8 +7,8 @@ module ROM
7
7
  # @example
8
8
  #
9
9
  #
10
- # class UserParams
11
- # include ROM::Model::Params
10
+ # class UserAttributes
11
+ # include ROM::Model::Attributes
12
12
  #
13
13
  # attribute :name
14
14
  #
@@ -19,53 +19,100 @@ module ROM
19
19
  # include ROM::Model::Validator
20
20
  # end
21
21
  #
22
- # params = UserParams.new(name: '')
23
- # UserValidator.call(params) # raises ValidationError
22
+ # attrs = UserAttributes.new(name: '')
23
+ # UserValidator.call(attrs) # raises ValidationError
24
24
  #
25
25
  # @api public
26
26
  module Validator
27
+ # Inclusion hook that extends a class with required interfaces
28
+ #
29
+ # @api private
27
30
  def self.included(base)
28
31
  base.class_eval do
29
32
  extend ClassMethods
30
33
  include ActiveModel::Validations
31
- include Equalizer.new(:params, :errors)
34
+ include Equalizer.new(:attributes, :errors)
32
35
  end
33
36
  end
34
37
 
35
- attr_reader :params
36
- delegate :model_name, to: :params
38
+ # @return [Model::Attributes]
39
+ #
40
+ # @api private
41
+ attr_reader :attributes
37
42
 
38
- def initialize(params)
39
- @params = params
43
+ delegate :model_name, to: :attributes
44
+
45
+ # @api private
46
+ def initialize(attributes)
47
+ @attributes = attributes
40
48
  end
41
49
 
50
+ # @return [Model::Attributes]
51
+ #
52
+ # @api public
42
53
  def to_model
43
- params
54
+ attributes
44
55
  end
45
56
 
57
+ # Trigger validations and return attributes on success
58
+ #
59
+ # @raises ValidationError
60
+ #
61
+ # @return [Model::Attributes]
62
+ #
63
+ # @api public
46
64
  def call
47
65
  raise ValidationError, errors unless valid?
48
- params
66
+ attributes
49
67
  end
50
68
 
51
69
  private
52
70
 
71
+ # This is needed for ActiveModel::Validations to work properly
72
+ # as it expects the object to provide attribute values. Meh.
73
+ #
74
+ # @api private
53
75
  def method_missing(name)
54
- params[name]
76
+ attributes[name]
55
77
  end
56
78
 
57
79
  module ClassMethods
80
+ # Set relation name for a validator
81
+ #
82
+ # This is needed for validators that require database access
83
+ #
84
+ # @example
85
+ #
86
+ # class UserValidator
87
+ # include ROM::Model::Validator
88
+ #
89
+ # relation :users
90
+ #
91
+ # validates :name, uniqueness: true
92
+ # end
93
+ #
94
+ # @return [Symbol]
95
+ #
96
+ # @api public
58
97
  def relation(name = nil)
59
98
  @relation = name if name
60
99
  @relation
61
100
  end
62
101
 
102
+ # FIXME: this looks like not needed
63
103
  def model_name
64
- params.model_name
104
+ attributes.model_name
65
105
  end
66
106
 
67
- def call(params)
68
- validator = new(params)
107
+ # Trigger validation for specific attributes
108
+ #
109
+ # @param [Model::Attributes] attributes The attributes for validation
110
+ #
111
+ # @raises [ValidationError]
112
+ #
113
+ # @return [Model::Attributes]
114
+ def call(attributes)
115
+ validator = new(attributes)
69
116
  validator.call
70
117
  end
71
118
  end
@@ -3,33 +3,69 @@ require 'active_model/validator'
3
3
  module ROM
4
4
  module Model
5
5
  module Validator
6
+ # Uniqueness validation
7
+ #
8
+ # @api public
6
9
  class UniquenessValidator < ActiveModel::EachValidator
7
- attr_reader :klass, :message
10
+ # Relation validator class
11
+ #
12
+ # @api private
13
+ attr_reader :klass
8
14
 
15
+ # error message
16
+ #
17
+ # @return [String, Symbol]
18
+ #
19
+ # @api private
20
+ attr_reader :message
21
+
22
+ # @api private
9
23
  def initialize(options)
10
24
  super
11
25
  @klass = options.fetch(:class)
12
26
  @message = options.fetch(:message) { :taken }
13
27
  end
14
28
 
29
+ # Hook called by ActiveModel internally
30
+ #
31
+ # @api private
15
32
  def validate_each(validator, name, value)
16
33
  validator.errors.add(name, message) unless unique?(name, value)
17
34
  end
18
35
 
19
36
  private
20
37
 
38
+ # Get relation object from the rom env
39
+ #
40
+ # @api private
21
41
  def relation
22
42
  rom.relations[relation_name]
23
43
  end
24
44
 
45
+ # Relation name defined on the validator class
46
+ #
47
+ # @api private
25
48
  def relation_name
26
49
  klass.relation
27
50
  end
28
51
 
52
+ # Shortcut to access global rom env
53
+ #
54
+ # @return [ROM::Env]
55
+ #
56
+ # @api private
29
57
  def rom
30
58
  ROM.env
31
59
  end
32
60
 
61
+ # Ask relation if a given attribute value is unique
62
+ #
63
+ # This uses `Relation#unique?` interface that not all adapters can
64
+ # implement.
65
+ #
66
+ # @return [TrueClass,FalseClass]
67
+ #
68
+ # @api private
33
69
  def unique?(name, value)
34
70
  relation.unique?(name => value)
35
71
  end
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  module Rails
3
- VERSION = "0.3.0.beta1".freeze
3
+ VERSION = "0.3.0.rc1".freeze
4
4
  end
5
5
  end
data/rom-rails.gemspec CHANGED
@@ -17,10 +17,10 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_runtime_dependency 'rom', '~> 0.6.0.beta1'
20
+ spec.add_runtime_dependency 'rom', '~> 0.6.0.rc1'
21
21
  spec.add_runtime_dependency 'addressable', '~> 2.3'
22
22
  spec.add_runtime_dependency 'charlatan', '~> 0.1'
23
- spec.add_runtime_dependency 'virtus', '~> 1.0', '>= 1.0.4'
23
+ spec.add_runtime_dependency 'virtus', '~> 1.0', '>= 1.0.5'
24
24
  spec.add_runtime_dependency 'railties', ['>= 3.0', '< 5.0']
25
25
 
26
26
  spec.add_development_dependency "bundler"
@@ -3,11 +3,14 @@ class UsersController < ApplicationController
3
3
  head :bad_request
4
4
  end
5
5
 
6
- relation 'users.index', only: :index
7
- relation 'users.by_name', only: :search, requires: :name
8
-
9
6
  def index
10
- render
7
+ render :index, locals: { users: rom.relation(:users).as(:users) }
8
+ end
9
+
10
+ def search
11
+ render :index, locals: {
12
+ users: rom.relation(:users).as(:users).by_name(params[:name])
13
+ }
11
14
  end
12
15
 
13
16
  def new
@@ -40,10 +43,6 @@ class UsersController < ApplicationController
40
43
  end
41
44
  end
42
45
 
43
- def search
44
- render :index
45
- end
46
-
47
46
  def ping
48
47
  head :ok
49
48
  end
@@ -1,9 +1,9 @@
1
1
  class NewUserForm < UserForm
2
2
  commands users: :create
3
3
 
4
- params.timestamps(:created_at)
4
+ attributes.timestamps(:created_at)
5
5
 
6
6
  def commit!
7
- users.try { users.create.call(params) }
7
+ users.try { users.create.call(attributes) }
8
8
  end
9
9
  end
@@ -1,9 +1,9 @@
1
1
  class UpdateUserForm < UserForm
2
2
  commands users: :update
3
3
 
4
- params.timestamps(:updated_at)
4
+ attributes.timestamps(:updated_at)
5
5
 
6
6
  def commit!
7
- users.try { users.update.by_id(id).set(params) }
7
+ users.try { users.update.by_id(id).set(attributes) }
8
8
  end
9
9
  end
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe ROM::Model::Params do
4
- let(:params) do
3
+ describe ROM::Model::Attributes do
4
+ let(:attributes) do
5
5
  Class.new do
6
- include ROM::Model::Params
6
+ include ROM::Model::Attributes
7
7
 
8
8
  attribute :name, String
9
9
 
@@ -13,32 +13,32 @@ describe ROM::Model::Params do
13
13
 
14
14
  describe '.timestamps' do
15
15
  it 'provides a way to specify timestamps with default values' do
16
- expect(params.new.created_at).to be_a(DateTime)
17
- expect(params.new.updated_at).to be_a(DateTime)
16
+ expect(attributes.new.created_at).to be_a(DateTime)
17
+ expect(attributes.new.updated_at).to be_a(DateTime)
18
18
  end
19
19
 
20
20
  context 'passing in arbritrary names' do
21
21
  it 'excludes :created_at when passing in :updated_at' do
22
- params = Class.new {
23
- include ROM::Model::Params
22
+ attributes = Class.new {
23
+ include ROM::Model::Attributes
24
24
 
25
25
  timestamps(:updated_at)
26
26
  }
27
27
 
28
- model = params.new
28
+ model = attributes.new
29
29
 
30
30
  expect(model).not_to respond_to(:created_at)
31
31
  expect(model).to respond_to(:updated_at)
32
32
  end
33
33
 
34
34
  it 'accepts multiple timestamp attribute names' do
35
- params = Class.new {
36
- include ROM::Model::Params
35
+ attributes = Class.new {
36
+ include ROM::Model::Attributes
37
37
 
38
38
  timestamps(:published_at, :revised_at)
39
39
  }
40
40
 
41
- model = params.new
41
+ model = attributes.new
42
42
 
43
43
  expect(model).to respond_to(:published_at)
44
44
  expect(model).to respond_to(:revised_at)
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  describe 'User model mapping' do
4
4
  let(:rom) { ROM.env }
5
5
 
6
- let(:users) { rom.read(:users) }
6
+ let(:users) { rom.relation(:users).as(:users) }
7
7
 
8
8
  before do
9
9
  rom.relations.users.insert(name: 'Piotr', email: 'piotr@test.com')
@@ -37,7 +37,7 @@ describe ROM::Generators::FormGenerator do
37
37
  end
38
38
 
39
39
  def commit!
40
- users.try { users.create.call(params) }
40
+ users.try { users.create.call(attributes) }
41
41
  end
42
42
 
43
43
  end
@@ -76,7 +76,7 @@ describe ROM::Generators::FormGenerator do
76
76
  end
77
77
 
78
78
  def commit!
79
- users.try { users.update.by_id(id).set(params) }
79
+ users.try { users.update.by_id(id).set(attributes) }
80
80
  end
81
81
 
82
82
  end
@@ -17,8 +17,8 @@ describe ROM::Generators::MapperGenerator do
17
17
  file 'user_mapper.rb' do
18
18
  contains <<-CONTENT.strip_heredoc
19
19
  class UserMapper < ROM::Mapper
20
- # relation :users
21
- #
20
+ relation :users
21
+
22
22
  # specify model and attributes ie
23
23
  #
24
24
  # model User
@@ -25,17 +25,21 @@ describe 'Form' do
25
25
 
26
26
  describe '.build' do
27
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
- }
28
+ input = { 'name' => '' }
33
29
 
34
30
  form_object = form.build(input)
35
31
 
36
- expect(form_object.params).to eql(
37
- name: 'Jane', hash: { two: 2 }, array: [{ four: 4 }, 5]
38
- )
32
+ expect(form_object.attributes.to_h).to eql(email: nil)
33
+ end
34
+
35
+ it 'exposes param values' do
36
+ params = { 'email' => 'jane@doe.org' }
37
+ form_object = form.build(params)
38
+ expect(form_object.email).to eql('jane@doe.org')
39
+
40
+ params = { email: 'jane@doe.org' }
41
+ form_object = form.build(params)
42
+ expect(form_object.email).to eql('jane@doe.org')
39
43
  end
40
44
  end
41
45
 
@@ -48,7 +52,7 @@ describe 'Form' do
48
52
  validations { validates :name, presence: true }
49
53
 
50
54
  def commit!
51
- users.try { users.create.call(params) }
55
+ users.try { users.create.call(attributes) }
52
56
  end
53
57
  }
54
58
 
@@ -94,16 +98,16 @@ describe 'Form' do
94
98
  end
95
99
 
96
100
  describe '.model_name' do
97
- it 'delegates to Params.model_name' do
98
- expect(form.model_name).to be(form.params.model_name)
101
+ it 'delegates to Attributes.model_name' do
102
+ expect(form.model_name).to be(form.attributes.model_name)
99
103
  end
100
104
  end
101
105
 
102
106
  describe 'input DSL' do
103
107
  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')
108
+ expect(form.const_defined?(:Attributes)).to be(true)
109
+ expect(form.attributes.attribute_set.map(&:name)).to eql([:email])
110
+ expect(form.attributes.model_name).to eql('User')
107
111
  end
108
112
 
109
113
  it 'defines a model' do
@@ -278,8 +282,8 @@ describe 'Form' do
278
282
  end
279
283
 
280
284
  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)
285
+ expect(child_form.attributes.attribute_set[:email]).to_not be(nil)
286
+ expect(child_form.attributes).to_not be(form.attributes)
283
287
  end
284
288
 
285
289
  it 'copies model' do
@@ -1,11 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'Validation' do
4
- subject(:validator) { user_validator.new(params) }
4
+ subject(:validator) { user_validator.new(attributes) }
5
5
 
6
- let(:user_params) do
6
+ let(:user_attrs) do
7
7
  Class.new {
8
- include ROM::Model::Params
8
+ include ROM::Model::Attributes
9
9
 
10
10
  attribute :name, String
11
11
  attribute :email, String
@@ -28,24 +28,24 @@ describe 'Validation' do
28
28
  end
29
29
 
30
30
  describe '#call' do
31
- let(:params) { {} }
31
+ let(:attributes) { {} }
32
32
 
33
- it 'raises validation error when params are not valid' do
33
+ it 'raises validation error when attributes are not valid' do
34
34
  expect { validator.call }.to raise_error(ROM::Model::ValidationError)
35
35
  end
36
36
  end
37
37
 
38
38
  describe "#validate" do
39
- let(:params) { {} }
39
+ let(:attributes) { {} }
40
40
 
41
- it "sets errors when params are not valid" do
41
+ it "sets errors when attributes are not valid" do
42
42
  validator.validate
43
43
  expect(validator.errors[:name]).to eql(["can't be blank"])
44
44
  end
45
45
  end
46
46
 
47
47
  describe ':presence' do
48
- let(:params) { user_params.new(name: '') }
48
+ let(:attributes) { user_attrs.new(name: '') }
49
49
 
50
50
  it 'sets error messages' do
51
51
  expect(validator).to_not be_valid
@@ -54,7 +54,7 @@ describe 'Validation' do
54
54
  end
55
55
 
56
56
  describe ':uniqueness' do
57
- let(:params) { user_params.new(name: 'Jane', email: 'jane@doe.org') }
57
+ let(:attributes) { user_attrs.new(name: 'Jane', email: 'jane@doe.org') }
58
58
 
59
59
  before do
60
60
  rom.relations.users.insert(name: 'Jane', email: 'jane@doe.org')