rom-rails 0.1.0 → 0.2.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +59 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +1 -1
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile +7 -2
  7. data/README.md +29 -18
  8. data/Rakefile +8 -0
  9. data/lib/generators/rom.rb +23 -0
  10. data/lib/generators/rom/commands/templates/commands.rb.erb +15 -0
  11. data/lib/generators/rom/commands_generator.rb +14 -0
  12. data/lib/generators/rom/mapper/templates/mapper.rb.erb +12 -0
  13. data/lib/generators/rom/mapper_generator.rb +14 -0
  14. data/lib/generators/rom/relation/templates/relation.rb.erb +8 -0
  15. data/lib/generators/rom/relation_generator.rb +14 -0
  16. data/lib/rom-rails.rb +5 -4
  17. data/lib/rom/model.rb +95 -0
  18. data/lib/rom/rails/configuration.rb +34 -0
  19. data/lib/rom/rails/controller_extension.rb +34 -1
  20. data/lib/rom/rails/inflections.rb +5 -0
  21. data/lib/rom/rails/railtie.rb +33 -73
  22. data/lib/rom/rails/version.rb +1 -1
  23. data/rom-rails.gemspec +5 -3
  24. data/spec/dummy/app/commands/users.rb +3 -5
  25. data/spec/dummy/app/controllers/users_controller.rb +14 -1
  26. data/spec/dummy/app/mappers/users.rb +1 -3
  27. data/spec/dummy/app/params/user_params.rb +7 -0
  28. data/spec/dummy/app/relations/users.rb +5 -5
  29. data/spec/dummy/app/validators/user_validator.rb +3 -0
  30. data/spec/dummy/config/boot.rb +1 -1
  31. data/spec/dummy/config/environments/development.rb +0 -1
  32. data/spec/dummy/config/environments/production.rb +0 -2
  33. data/spec/dummy/config/environments/test.rb +0 -4
  34. data/spec/dummy/config/routes.rb +2 -0
  35. data/spec/dummy/db/schema.rb +9 -2
  36. data/spec/dummy/spec/controllers/users_controller_spec.rb +29 -0
  37. data/spec/dummy/spec/features/users_spec.rb +11 -2
  38. data/spec/dummy/spec/integration/logger_spec.rb +3 -2
  39. data/spec/dummy/spec/integration/user_commands_spec.rb +21 -0
  40. data/spec/dummy/spec/integration/user_params_spec.rb +33 -0
  41. data/spec/lib/generators/commands_generator_spec.rb +40 -0
  42. data/spec/lib/generators/mapper_generator_spec.rb +37 -0
  43. data/spec/lib/generators/relation_generator_spec.rb +33 -0
  44. data/spec/spec_helper.rb +5 -0
  45. metadata +63 -10
  46. data/lib/rom/rom-rails.rb +0 -8
  47. data/spec/unit/configuration_spec.rb +0 -39
@@ -1,13 +1,46 @@
1
1
  module ROM
2
2
  module Rails
3
+ RelationParamsMissingError = Class.new(StandardError)
3
4
 
4
5
  module ControllerExtension
6
+ def self.included(klass)
7
+ klass.extend(ClassExtensions)
8
+ end
5
9
 
6
10
  def rom
7
11
  ::Rails.application.config.rom.env
8
12
  end
9
13
 
10
- end
14
+ module ClassExtensions
15
+ def relation(path, options)
16
+ root, method = path.split('.').map(&:to_sym)
17
+
18
+ name = options.fetch(:as) { root }
19
+ requires = Array(options.fetch(:requires) { [] })
20
+
21
+ before_filter(options.except(:as, :requires)) do
22
+ args = params.values_at(*requires)
11
23
 
24
+ if requires.any? && args.none?
25
+ raise RelationParamsMissingError
26
+ else
27
+ relation =
28
+ if args.any?
29
+ rom.read(root).send(method, *args)
30
+ else
31
+ rom.read(root).send(method)
32
+ end
33
+
34
+ instance_variable_set("@#{name}", relation.to_a)
35
+ end
36
+ end
37
+
38
+ unless respond_to?(name)
39
+ attr_reader name
40
+ helper_method name
41
+ end
42
+ end
43
+ end
44
+ end
12
45
  end
13
46
  end
@@ -0,0 +1,5 @@
1
+ require 'active_support/inflections'
2
+
3
+ ActiveSupport::Inflector.inflections do |inflect|
4
+ inflect.acronym 'ROM'
5
+ end
@@ -1,78 +1,52 @@
1
- module ROM
2
- module Rails
3
-
4
- class Configuration
5
- attr_reader :config, :setup, :env
6
-
7
- def self.build(app)
8
- root = app.config.root
9
- db_config = app.config.database_configuration[::Rails.env].symbolize_keys
10
-
11
- config = rewrite_config(root, db_config)
12
-
13
- new(config)
14
- end
15
-
16
- def self.rewrite_config(root, config)
17
- adapter = config[:adapter]
18
- database = config[:database]
19
- password = config[:password]
20
- username = config[:username]
21
- hostname = config.fetch(:hostname) { 'localhost' }
1
+ require 'rails'
22
2
 
23
- adapter = "sqlite" if adapter == "sqlite3"
3
+ require 'rom/rails/inflections'
4
+ require 'rom/rails/configuration'
5
+ require 'rom/rails/controller_extension'
24
6
 
25
- path =
26
- if adapter == "sqlite"
27
- "#{root}/#{database}"
28
- else
29
- db_path = [hostname, database].join('/')
7
+ if defined?(Spring)
8
+ Spring.after_fork { ROM::Rails::Railtie.disconnect }
9
+ end
30
10
 
31
- if username && password
32
- [[username, password].join(':'), db_path].join('@')
33
- else
34
- db_path
35
- end
36
- end
11
+ module ROM
12
+ module Rails
13
+ class Railtie < ::Rails::Railtie
14
+ def self.disconnect
15
+ return unless ROM.env
37
16
 
38
- { default: "#{adapter}://#{path}" }
17
+ ROM.env.repositories.each_value do |repository|
18
+ repository.adapter.disconnect
19
+ end
39
20
  end
40
21
 
41
- def initialize(config)
42
- @config = config
43
- @setup = ROM.setup(@config.symbolize_keys)
22
+ def self.load_all
23
+ %w(relations mappers commands).each do |type|
24
+ load_files(type, ::Rails.root)
25
+ end
44
26
  end
45
27
 
46
- def finalize
47
- @env = setup.finalize
28
+ def self.load_files(type, root)
29
+ Dir[root.join("app/#{type}/**/*.rb").to_s].each do |path|
30
+ load(path)
31
+ end
48
32
  end
49
- end
50
-
51
- class Railtie < ::Rails::Railtie
52
33
 
53
34
  initializer "rom.configure" do |app|
54
- config.rom = ROM::Rails::Configuration.build(app)
35
+ config.rom = Configuration.build(app)
55
36
  end
56
37
 
57
- initializer "rom.load_schema" do |app|
38
+ initializer "rom.load_schema" do |_app|
58
39
  require schema_file if schema_file.exist?
59
40
  end
60
41
 
61
- initializer "rom.load_relations" do |app|
62
- relation_files.each { |file| require file }
63
- end
64
-
65
- initializer "rom.load_mappers" do |app|
66
- mapper_files.each { |file| require file }
67
- end
68
-
69
- initializer "rom.load_commands" do |app|
70
- command_files.each { |file| require file }
71
- end
72
-
73
- config.after_initialize do |app|
74
- app.config.rom.finalize
75
- ApplicationController.send(:include, ControllerExtension)
42
+ initializer "rom:prepare" do |app|
43
+ config.to_prepare do |_config|
44
+ Railtie.disconnect
45
+ app.config.rom.setup!
46
+ app.config.rom.load!
47
+ app.config.rom.finalize!
48
+ ApplicationController.send(:include, ControllerExtension)
49
+ end
76
50
  end
77
51
 
78
52
  private
@@ -81,23 +55,9 @@ module ROM
81
55
  root.join('db/rom/schema.rb')
82
56
  end
83
57
 
84
- def relation_files
85
- Dir[root.join('app/relations/**/*.rb').to_s]
86
- end
87
-
88
- def mapper_files
89
- Dir[root.join('app/mappers/**/*.rb').to_s]
90
- end
91
-
92
- def command_files
93
- Dir[root.join('app/commands/**/*.rb').to_s]
94
- end
95
-
96
58
  def root
97
59
  ::Rails.root
98
60
  end
99
-
100
61
  end
101
-
102
62
  end
103
63
  end
@@ -1,5 +1,5 @@
1
1
  module ROM
2
2
  module Rails
3
- VERSION = "0.1.0".freeze
3
+ VERSION = "0.2.0".freeze
4
4
  end
5
5
  end
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
8
8
  spec.version = ROM::Rails::VERSION.dup
9
9
  spec.authors = ["Piotr Solnica"]
10
10
  spec.email = ["piotr.solnica@gmail.com"]
11
- spec.summary = %q{Integrate Ruby Object Mapper with Rails}
12
- spec.homepage = ""
11
+ spec.summary = 'Integrate Ruby Object Mapper with Rails'
12
+ spec.homepage = "http://rom-rb.org"
13
13
  spec.license = "MIT"
14
14
 
15
15
  spec.files = `git ls-files -z`.split("\x0")
@@ -17,9 +17,11 @@ 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.4', '>= 0.4.0'
20
+ spec.add_runtime_dependency 'rom', '~> 0.5', '>= 0.5.0'
21
+ spec.add_runtime_dependency 'virtus', '~> 1.0'
21
22
  spec.add_runtime_dependency 'railties', ['>= 3.0', '< 5.0']
22
23
 
23
24
  spec.add_development_dependency "bundler"
24
25
  spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rubocop", "~> 0.28.0"
25
27
  end
@@ -1,9 +1,7 @@
1
- setup = Rails.application.config.rom.setup
2
-
3
- setup.commands(:users) do
4
-
1
+ ROM.commands(:users) do
5
2
  define(:create) do
3
+ input UserParams
4
+ validator UserValidator
6
5
  result :one
7
6
  end
8
-
9
7
  end
@@ -1,7 +1,20 @@
1
1
  class UsersController < ApplicationController
2
+ rescue_from ROM::Rails::RelationParamsMissingError do
3
+ head :bad_request
4
+ end
5
+
6
+ relation 'users.index', only: :index
7
+ relation 'users.by_name', only: :search, requires: :name
2
8
 
3
9
  def index
4
- render locals: { users: rom.read(:users).to_a }
10
+ render
5
11
  end
6
12
 
13
+ def search
14
+ render :index
15
+ end
16
+
17
+ def ping
18
+ head :ok
19
+ end
7
20
  end
@@ -1,6 +1,4 @@
1
- setup = Rails.application.config.rom.setup
2
-
3
- setup.mappers do
1
+ ROM.mappers do
4
2
  define(:users) do
5
3
  model User
6
4
 
@@ -0,0 +1,7 @@
1
+ class UserParams
2
+ include ROM::Model::Params
3
+
4
+ attribute :name, String
5
+
6
+ validates :name, presence: true
7
+ end
@@ -1,9 +1,9 @@
1
- setup = Rails.application.config.rom.setup
2
-
3
- setup.relation(:users) do
1
+ ROM.relation(:users) do
2
+ def index
3
+ order(:name)
4
+ end
4
5
 
5
6
  def by_name(name)
6
- where(name: name)
7
+ index.where(name: name)
7
8
  end
8
-
9
9
  end
@@ -0,0 +1,3 @@
1
+ class UserValidator
2
+ include ROM::Model::Validator
3
+ end
@@ -1,4 +1,4 @@
1
1
  # Set up gems listed in the Gemfile.
2
2
  ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
3
3
 
4
- require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
4
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
@@ -15,5 +15,4 @@ Dummy::Application.configure do
15
15
 
16
16
  # Print deprecation notices to the Rails logger.
17
17
  config.active_support.deprecation = :log
18
-
19
18
  end
@@ -22,7 +22,6 @@ Dummy::Application.configure do
22
22
  # Disable Rails's static asset server (Apache or nginx will already do this).
23
23
  config.serve_static_assets = false
24
24
 
25
-
26
25
  # Specifies the header that your server uses for sending files.
27
26
  # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
28
27
  # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
@@ -45,7 +44,6 @@ Dummy::Application.configure do
45
44
  # Enable serving of images, stylesheets, and JavaScripts from an asset server.
46
45
  # config.action_controller.asset_host = "http://assets.example.com"
47
46
 
48
-
49
47
  # Ignore bad email addresses and do not raise email delivery errors.
50
48
  # Set this to true and configure the email server for immediate delivery to raise delivery errors.
51
49
  # config.action_mailer.raise_delivery_errors = false
@@ -12,10 +12,6 @@ Dummy::Application.configure do
12
12
  # preloads Rails for running tests, you may have to set it to true.
13
13
  config.eager_load = false
14
14
 
15
- # Configure static asset server for tests with Cache-Control for performance.
16
- config.serve_static_assets = true
17
- config.static_cache_control = "public, max-age=3600"
18
-
19
15
  # Show full error reports and disable caching.
20
16
  config.consider_all_requests_local = true
21
17
  config.action_controller.perform_caching = false
@@ -1,3 +1,5 @@
1
1
  Dummy::Application.routes.draw do
2
2
  get '/users' => 'users#index'
3
+ get '/users/search' => 'users#search'
4
+ get '/users/ping' => 'users#ping'
3
5
  end
@@ -11,10 +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: 20141110205016) do
14
+ ActiveRecord::Schema.define(version: 20141220203134) do
15
+ create_table "cars", force: true do |_t|
16
+ end
17
+
18
+ create_table "planes", force: true do |_t|
19
+ end
20
+
21
+ create_table "stuffs", force: true do |_t|
22
+ end
15
23
 
16
24
  create_table "users", force: true do |t|
17
25
  t.string "name"
18
26
  end
19
-
20
27
  end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe UsersController, type: :controller do
4
+ describe 'injected relations' do
5
+ it 'exposes relation without required params' do
6
+ get :index
7
+
8
+ expect(controller.users).to eql(rom.read(:users).index.to_a)
9
+ end
10
+
11
+ it 'exposes relation with required params' do
12
+ get :search, name: 'Jane'
13
+
14
+ expect(controller.users).to eql(rom.read(:users).by_name('Jane').to_a)
15
+ end
16
+
17
+ it 'halts processing when required params are missing' do
18
+ get :search
19
+
20
+ expect(response.status).to be(400)
21
+ end
22
+
23
+ it 'skips injecting relation when :only option is used' do
24
+ get :ping
25
+
26
+ expect(controller.users).to be(nil)
27
+ end
28
+ end
29
+ end
@@ -2,12 +2,21 @@ require 'spec_helper'
2
2
 
3
3
  feature 'Users' do
4
4
  background do
5
- Rails.application.config.rom.env.relations.users.insert(name: 'Piotr')
5
+ rom.relations.users.insert(name: 'Jane')
6
+ rom.relations.users.insert(name: 'Joe')
6
7
  end
7
8
 
8
9
  scenario 'I see user list on index page' do
9
10
  visit '/users'
10
11
 
11
- expect(page).to have_content('Piotr')
12
+ expect(page).to have_content('Jane')
13
+ expect(page).to have_content('Joe')
14
+ end
15
+
16
+ scenario 'I can search users' do
17
+ visit '/users/search?name=Jane'
18
+
19
+ expect(page).to have_content('Jane')
20
+ expect(page).to_not have_content('Joe')
12
21
  end
13
22
  end
@@ -4,8 +4,9 @@ describe 'ROM logger' do
4
4
  let(:rom) { Rails.application.config.rom.env }
5
5
 
6
6
  it 'sets up rails logger for all repositories' do
7
- pending 'this will be re-enabled once we have feature detection on adapters ' +
8
- 'and in case of missing rails-log-subscriber support we will set logger to Rails.logger'
7
+ pending 'this will be re-enabled once we have feature detection on ' \
8
+ 'adapters and in case of missing rails-log-subscriber support we ' \
9
+ 'will set logger to Rails.logger'
9
10
  rom.repositories.each_value do |repository|
10
11
  expect(repository.logger).to be(Rails.logger)
11
12
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'User commands' do
4
+ subject(:users) { rom.command(:users) }
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: 1, 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
+ end