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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +26 -0
  3. data/CHANGELOG.md +17 -0
  4. data/README.md +4 -0
  5. data/lib/generators/rom/commands/templates/create.rb.erb +10 -0
  6. data/lib/generators/rom/commands/templates/delete.rb.erb +7 -0
  7. data/lib/generators/rom/commands/templates/update.rb.erb +10 -0
  8. data/lib/generators/rom/commands_generator.rb +33 -5
  9. data/lib/generators/rom/form/templates/edit_form.rb.erb +24 -0
  10. data/lib/generators/rom/form/templates/new_form.rb.erb +24 -0
  11. data/lib/generators/rom/form_generator.rb +39 -0
  12. data/lib/generators/rom/mapper/templates/mapper.rb.erb +9 -11
  13. data/lib/generators/rom/mapper_generator.rb +11 -1
  14. data/lib/generators/rom/relation/templates/relation.rb.erb +3 -2
  15. data/lib/generators/rom/relation_generator.rb +16 -1
  16. data/lib/rom-rails.rb +0 -5
  17. data/lib/rom/model.rb +7 -90
  18. data/lib/rom/rails/active_record/configuration.rb +105 -0
  19. data/lib/rom/rails/configuration.rb +4 -27
  20. data/lib/rom/rails/model/form.rb +59 -0
  21. data/lib/rom/rails/model/form/dsl.rb +173 -0
  22. data/lib/rom/rails/model/params.rb +72 -0
  23. data/lib/rom/rails/model/validator.rb +74 -0
  24. data/lib/rom/rails/model/validator/uniqueness_validator.rb +39 -0
  25. data/lib/rom/rails/railtie.rb +65 -29
  26. data/lib/rom/rails/version.rb +1 -1
  27. data/rom-rails.gemspec +3 -1
  28. data/spec/dummy/app/commands/tasks.rb +5 -0
  29. data/spec/dummy/app/commands/users.rb +4 -10
  30. data/spec/dummy/app/controllers/users_controller.rb +30 -0
  31. data/spec/dummy/app/forms/new_user_form.rb +9 -0
  32. data/spec/dummy/app/forms/update_user_form.rb +9 -0
  33. data/spec/dummy/app/forms/user_form.rb +15 -0
  34. data/spec/dummy/app/mappers/users.rb +6 -6
  35. data/spec/dummy/app/relations/tasks.rb +9 -0
  36. data/spec/dummy/app/relations/users.rb +5 -1
  37. data/spec/dummy/app/views/users/edit.html.erb +6 -0
  38. data/spec/dummy/app/views/users/new.html.erb +6 -0
  39. data/spec/dummy/config/routes.rb +5 -1
  40. data/spec/dummy/db/migrate/20141110205016_add_users.rb +2 -0
  41. data/spec/dummy/db/migrate/20150202194440_create_tasks.rb +7 -0
  42. data/spec/dummy/db/schema.rb +8 -8
  43. data/spec/dummy/spec/features/users_spec.rb +30 -0
  44. data/spec/dummy/spec/integration/logger_spec.rb +1 -1
  45. data/spec/dummy/spec/integration/user_commands_spec.rb +2 -18
  46. data/spec/dummy/spec/integration/user_model_mapping_spec.rb +2 -2
  47. data/spec/dummy/spec/integration/user_params_spec.rb +30 -15
  48. data/spec/lib/active_record/configuration_spec.rb +98 -0
  49. data/spec/lib/generators/commands_generator_spec.rb +54 -14
  50. data/spec/lib/generators/form_generator_spec.rb +89 -0
  51. data/spec/lib/generators/mapper_generator_spec.rb +10 -12
  52. data/spec/lib/generators/relation_generator_spec.rb +16 -6
  53. data/spec/spec_helper.rb +1 -1
  54. data/spec/unit/form_spec.rb +297 -0
  55. data/spec/unit/{model_spec.rb → params_spec.rb} +0 -0
  56. data/spec/unit/validator_spec.rb +75 -0
  57. metadata +72 -20
  58. data/lib/generators/rom/commands/templates/commands.rb.erb +0 -15
  59. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  60. data/spec/dummy/app/params/user_params.rb +0 -7
  61. data/spec/dummy/app/validators/user_validator.rb +0 -3
@@ -11,17 +11,17 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20141220203134) do
15
- create_table "cars", force: true do |_t|
16
- end
14
+ ActiveRecord::Schema.define(version: 20150202194440) do
17
15
 
18
- create_table "planes", force: true do |_t|
16
+ create_table "tasks", force: :cascade do |t|
17
+ t.string "title"
19
18
  end
20
19
 
21
- create_table "stuffs", force: true do |_t|
20
+ create_table "users", force: :cascade do |t|
21
+ t.string "name"
22
+ t.string "email"
23
+ t.datetime "created_at"
24
+ t.datetime "updated_at"
22
25
  end
23
26
 
24
- create_table "users", force: true do |t|
25
- t.string "name"
26
- end
27
27
  end
@@ -13,6 +13,36 @@ feature 'Users' do
13
13
  expect(page).to have_content('Joe')
14
14
  end
15
15
 
16
+ scenario 'I save a new user' do
17
+ visit '/users/new'
18
+
19
+ click_on 'Create User'
20
+ expect(page).to have_content("can't be blank")
21
+
22
+ find('#user_email').set('jade@doe.org')
23
+ find('#user_name').set('Jade')
24
+ click_on 'Create User'
25
+
26
+ expect(page).to have_content('Jade')
27
+ expect(page).to have_content('Jane')
28
+ expect(page).to have_content('Joe')
29
+ end
30
+
31
+ scenario 'I edit an existing user' do
32
+ jane = rom.relations.users.by_name('Jane').first
33
+ visit "/users/#{jane[:id]}/edit"
34
+
35
+ click_on 'Update User'
36
+ expect(page).to have_content("can't be blank")
37
+
38
+ find('#user_email').set('jane.doe@example.org')
39
+ find('#user_name').set('Jane Doe')
40
+ click_on 'Update User'
41
+
42
+ expect(page).to have_content('Jane Doe')
43
+ expect(page).to have_content('Joe')
44
+ end
45
+
16
46
  scenario 'I can search users' do
17
47
  visit '/users/search?name=Jane'
18
48
 
@@ -1,7 +1,7 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'ROM logger' do
4
- let(:rom) { Rails.application.config.rom.env }
4
+ let(:rom) { ROM.env }
5
5
 
6
6
  it 'sets up rails logger for all repositories' do
7
7
  pending 'this will be re-enabled once we have feature detection on ' \
@@ -3,26 +3,10 @@ require 'spec_helper'
3
3
  describe 'User commands' do
4
4
  subject(:users) { rom.command(:users) }
5
5
 
6
- describe 'create' do
7
- it 'inserts user with valid params' do
8
- result = users.try { create(name: 'Jade') }
9
-
10
- expect(result.value).to eql(id: result.value[:id], name: 'Jade')
11
- end
12
-
13
- it 'returns error if params are not valid' do
14
- result = users.try { create(name: '') }
15
-
16
- expect(result.value).to be(nil)
17
- expect(result.error).to be_instance_of(ROM::Model::ValidationError)
18
- expect(result.error.messages[:name]).to include("can't be blank")
19
- end
20
- end
21
-
22
6
  describe 'delete' do
23
7
  it 'deletes record' do
24
- users.create.call(name: 'Piotr')
25
- result = users.try { delete(:by_name, 'Piotr') }
8
+ rom.relations.users.insert(name: 'Piotr', email: 'piotr@test.com')
9
+ result = users.try { users.delete.by_name('Piotr') }
26
10
 
27
11
  expect(result.error).to be(nil)
28
12
  end
@@ -1,12 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'User model mapping' do
4
- let(:rom) { Rails.application.config.rom.env }
4
+ let(:rom) { ROM.env }
5
5
 
6
6
  let(:users) { rom.read(:users) }
7
7
 
8
8
  before do
9
- rom.command(:users).try { create(name: 'Piotr') }
9
+ rom.relations.users.insert(name: 'Piotr', email: 'piotr@test.com')
10
10
  end
11
11
 
12
12
  it 'works' do
@@ -5,29 +5,44 @@ describe ROM::Model::Params do
5
5
  Class.new do
6
6
  include ROM::Model::Params
7
7
 
8
- param_key :test
9
8
  attribute :name, String
10
- validates :name, presence: true
11
9
 
12
- def self.name
13
- 'Test'
14
- end
10
+ timestamps
15
11
  end
16
12
  end
17
13
 
18
- describe '#valid?' do
19
- it 'returns true when attributes are valid' do
20
- user_params = params.new(name: 'Jane')
21
- expect(user_params).to be_valid
14
+ describe '.timestamps' do
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)
22
18
  end
23
19
 
24
- it 'returns false when attributes are not valid' do
25
- user_params = params.new(name: '')
26
- expect(user_params).not_to be_valid
27
- end
20
+ context 'passing in arbritrary names' do
21
+ it 'excludes :created_at when passing in :updated_at' do
22
+ params = Class.new {
23
+ include ROM::Model::Params
24
+
25
+ timestamps(:updated_at)
26
+ }
27
+
28
+ model = params.new
29
+
30
+ expect(model).not_to respond_to(:created_at)
31
+ expect(model).to respond_to(:updated_at)
32
+ end
33
+
34
+ it 'accepts multiple timestamp attribute names' do
35
+ params = Class.new {
36
+ include ROM::Model::Params
37
+
38
+ timestamps(:published_at, :revised_at)
39
+ }
28
40
 
29
- it 'sets up AM name' do
30
- expect(params.model_name.param_key).to eql('test')
41
+ model = params.new
42
+
43
+ expect(model).to respond_to(:published_at)
44
+ expect(model).to respond_to(:revised_at)
45
+ end
31
46
  end
32
47
  end
33
48
  end
@@ -0,0 +1,98 @@
1
+ require 'spec_helper'
2
+ require 'rom/rails/active_record/configuration'
3
+
4
+ describe ROM::Rails::ActiveRecord::Configuration do
5
+ let(:root) { Pathname.new('/path/to/app') }
6
+
7
+ def uri_for(config)
8
+ result = read(config)
9
+ result.is_a?(Hash) ? result[:uri] : result
10
+ end
11
+
12
+ def read(config)
13
+ described_class.build(config.merge(root: root))
14
+ end
15
+
16
+ def parse(uri)
17
+ URI.parse(uri.gsub(/^jdbc:/, ''))
18
+ end
19
+
20
+ it 'raises an error without specifying a database'
21
+
22
+ context 'with postgresql adapter' do
23
+ it 'rewrites the scheme' do
24
+ uri = uri_for(adapter: 'postgresql', database: 'test')
25
+ expect(parse(uri).scheme).to eql('postgres')
26
+ end
27
+
28
+ it 'does not use jdbc even on jruby' do
29
+ uri = uri_for(adapter: 'postgresql', database: 'test')
30
+ expect(uri).to_not start_with('jdbc:')
31
+ end
32
+
33
+ it 'only includes username if no password is given' do
34
+ uri = uri_for(
35
+ adapter: 'postgresql',
36
+ host: 'example.com',
37
+ database: 'test',
38
+ username: 'user'
39
+ )
40
+
41
+ expect(parse(uri).userinfo).to eql('user')
42
+ end
43
+
44
+ it 'includes username and password if both are given' do
45
+ uri = uri_for(
46
+ adapter: 'postgresql',
47
+ database: 'test',
48
+ username: 'user',
49
+ password: 'password',
50
+ host: 'example.com'
51
+ )
52
+
53
+ expect(parse(uri).userinfo).to eql('user:password')
54
+ end
55
+
56
+ it 'omits userinfo if neither username nor password are given' do
57
+ uri = uri_for(adapter: 'postgresql', database: 'test')
58
+ expect(parse(uri).userinfo).to be_nil
59
+ end
60
+
61
+ it 'properly handles configuration without a host' do
62
+ uri = uri_for(adapter: 'postgresql', database: 'test')
63
+ expect(uri).to eql('postgres:///test')
64
+ end
65
+ end
66
+
67
+ context 'with mysql adapter' do
68
+ it 'sets default password to an empty string' do
69
+ uri = uri_for(adapter: 'mysql', database: 'test', username: 'root', host: 'example.com')
70
+ expect(parse(uri).userinfo).to eql('root:')
71
+ end
72
+
73
+ it 'uses jdbc only on jruby' do
74
+ uri = uri_for(adapter: 'mysql', database: 'test')
75
+ expect(uri.starts_with?('jdbc:')).to be(RUBY_ENGINE == 'jruby')
76
+ end
77
+ end
78
+
79
+ context 'with sqlite3 adapter' do
80
+ let(:database) { Pathname.new('db/development.sqlite3') }
81
+ let(:config) { { adapter: adapter, database: database } }
82
+
83
+ it 'rewrites the scheme' do
84
+ uri = uri_for(adapter: 'sqlite3', database: database)
85
+ expect(parse(uri).scheme).to eql('sqlite')
86
+ end
87
+
88
+ it 'uses jdbc only on jruby' do
89
+ uri = uri_for(adapter: 'sqlite3', database: database)
90
+ expect(uri.starts_with?('jdbc:')).to be(RUBY_ENGINE == 'jruby')
91
+ end
92
+
93
+ it 'expands the path' do
94
+ uri = uri_for(adapter: 'sqlite3', database: database)
95
+ expect(parse(uri).path).to eql(root.join(database).to_s)
96
+ end
97
+ end
98
+ end
@@ -5,36 +5,76 @@ require 'generators/rom/commands_generator'
5
5
  describe ROM::Generators::CommandsGenerator do
6
6
  destination File.expand_path('../../../../tmp', __FILE__)
7
7
 
8
- before(:all) do
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
+
15
+ default_adapter = ROM.adapters.keys.first
16
+
14
17
  expect(destination_root).to have_structure {
15
18
  directory 'app' do
16
19
  directory 'commands' do
17
- file 'users.rb' do
18
- contains <<-CONTENT.strip_heredoc
19
- ROM.commands(:users) do
20
+ directory 'users' do
21
+ file 'create.rb' do
22
+ contains <<-CONTENT.strip_heredoc
23
+ module UserCommands
24
+ class Create < ROM::Commands::Create[:#{default_adapter}]
25
+ relation :users
26
+ register_as :create
27
+ result :one
20
28
 
21
- define(:create) do
22
- result :one
29
+ # define a validator to use
30
+ # validator UserValidator
31
+ end
23
32
  end
33
+ CONTENT
34
+ end
24
35
 
25
- define(:update) do
26
- result :one
27
- end
36
+ file 'update.rb' do
37
+ contains <<-CONTENT.strip_heredoc
38
+ module UserCommands
39
+ class Update < ROM::Commands::Update[:#{default_adapter}]
40
+ relation :users
41
+ register_as :update
42
+ result :one
28
43
 
29
- define(:delete) do
30
- result :one
44
+ # define a validator to use
45
+ # validator UserValidator
46
+ end
31
47
  end
48
+ CONTENT
49
+ end
32
50
 
33
- end
34
- CONTENT
51
+ file 'delete.rb' do
52
+ contains <<-CONTENT.strip_heredoc
53
+ module UserCommands
54
+ class Delete < ROM::Commands::Delete[:#{default_adapter}]
55
+ relation :users
56
+ register_as :delete
57
+ result :one
58
+ end
59
+ end
60
+ CONTENT
61
+ end
35
62
  end
36
63
  end
37
64
  end
38
65
  }
39
66
  end
67
+
68
+ specify "with given adapter" do
69
+ run_generator ['users', '--adapter=memory']
70
+
71
+ create = File.read(File.join(destination_root, 'app', 'commands', 'users', 'create.rb'))
72
+ expect(create).to include("class Create < ROM::Commands::Create[:memory]")
73
+
74
+ update = File.read(File.join(destination_root, 'app', 'commands', 'users', 'update.rb'))
75
+ expect(update).to include("class Update < ROM::Commands::Update[:memory]")
76
+
77
+ delete = File.read(File.join(destination_root, 'app', 'commands', 'users', 'delete.rb'))
78
+ expect(delete).to include("class Delete < ROM::Commands::Delete[:memory]")
79
+ end
40
80
  end
@@ -0,0 +1,89 @@
1
+ require 'spec_helper'
2
+
3
+ require 'generators/rom/form_generator'
4
+
5
+ describe ROM::Generators::FormGenerator do
6
+ destination File.expand_path('../../../../tmp', __FILE__)
7
+
8
+ before(:each) do
9
+ prepare_destination
10
+ end
11
+
12
+ specify "a create form" do
13
+ run_generator ['users', '--command=create']
14
+
15
+ expect(destination_root).to have_structure {
16
+ directory 'app' do
17
+ directory 'forms' do
18
+ file 'new_user_form.rb' do
19
+ contains <<-CONTENT.strip_heredoc
20
+ class NewUserForm < ROM::Model::Form
21
+ commands users: :create
22
+
23
+ input do
24
+ set_model_name 'User'
25
+
26
+ # define form input attributes
27
+ # attribute :name, String
28
+
29
+ timestamps
30
+ end
31
+
32
+ validations do
33
+ relation :users
34
+
35
+ # Add form validations
36
+ # validates :name, presence: true
37
+ end
38
+
39
+ def commit!
40
+ users.try { users.create.call(params) }
41
+ end
42
+
43
+ end
44
+ CONTENT
45
+ end
46
+ end
47
+ end
48
+ }
49
+ end
50
+
51
+ specify "an edit form" do
52
+ run_generator ['users', '--command=update']
53
+
54
+ expect(destination_root).to have_structure {
55
+ directory 'app' do
56
+ directory 'forms' do
57
+ file 'edit_user_form.rb' do
58
+ contains <<-CONTENT.strip_heredoc
59
+ class EditUserForm < ROM::Model::Form
60
+ commands users: :update
61
+
62
+ input do
63
+ set_model_name 'User'
64
+
65
+ # define form input attributes
66
+ # attribute :name, String
67
+
68
+ timestamps :updated_at
69
+ end
70
+
71
+ validations do
72
+ relation :users
73
+
74
+ # Add form validations
75
+ # validates :name, presence: true
76
+ end
77
+
78
+ def commit!
79
+ users.try { users.update.by_id(id).set(params) }
80
+ end
81
+
82
+ end
83
+ CONTENT
84
+ end
85
+ end
86
+ end
87
+ }
88
+ end
89
+ end