rom-rails 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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