repositor 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bd4aae918948fed1130511573293f27eb04186f6
4
- data.tar.gz: fd9fed701002b6723f1f2f92c0d162a4192eeaf8
3
+ metadata.gz: a5397ecf74b2b8bcffd0f97269bbf431c1f07a72
4
+ data.tar.gz: 4fe43a91b408049f3bf5029cfe3397785be327d3
5
5
  SHA512:
6
- metadata.gz: 9c69491ab1086fb5b8a976ca4b6c94ee1a7d4049407e32c0516c71961e342fa9ab0a42c6d28ec4bc06afd5ee2702653d77b4107e344e245994f1d63113050373
7
- data.tar.gz: 5de69c59cbfc9d6b96ee4fdd78119810241ee4e412b483b66ead93f96e065467a3fca6ec06f9aa98edfac867f65f35973dd1dbfa4075a543f0f5273342650aad
6
+ metadata.gz: f8204a1184c6a9523cb1247a0fdda409ce523a9458a27e459815b72ada0e9995cdfb72d46405ad38a54a17b22993cecee7ebaf646eadcebf8f63bc9102a266d3
7
+ data.tar.gz: 9dda4919b47be711e71f4aa003274d169cf01532e92343a12d16cce93c539d4f34cbca4504903dc723d7a83a1939cb2f795591cec850ddc3553f3166e91c8556
data/README.md CHANGED
@@ -21,11 +21,17 @@ bundle install
21
21
 
22
22
  This gem is an implementation of **Repository Pattern** described in book [Fearless Refactoring Rails Controllers](http://rails-refactoring.com/) by Andrzej Krzywda 2014 (c). Awesome book, recommend read for all who are scary open own controller files ;)
23
23
 
24
- The main reason to user **RepoObject** is that your controller don't communicate with ORM layer (ActiveRecord or Mongoid). It must communicate with Repo layer so you are not stricted about your database adapter. If in future you will want to change it, you will need just to reconfigure your Repository layer. Sounds nice. Let's try it..
24
+ I split record instance manage and collection manage into two almost same (but not) layers - Repos & Queries
25
25
 
26
- With some helps of helper method your controller can be only 30-40 lines of code. Nothing more.
26
+ **Repo** - for single record (:find, :new, :create, :update, :destroy)
27
27
 
28
- With RepoObject you controller could look something like this:
28
+ **Query** - for collection of records (:all, :where and others)
29
+
30
+ The main reason to user **RepoObject** is that your controller don't communicate with ORM layer (ActiveRecord or Mongoid). It will communicate with Repo/Query so you are not stricted about your database adapter or data API. It's some sort of anti-corruption layer also. If in future you will want to change it, you will need just to reconfigure your Repository layer. Sounds nice. Let's try it..
31
+
32
+ With some support of `helper_method` your controller can be only 50-60 lines of code. Nothing more.
33
+
34
+ With **Repo** and **Query** you controller could look something like this:
29
35
  ```ruby
30
36
  class ProductsController < ApplicationController
31
37
 
@@ -68,16 +74,23 @@ class ProductsController < ApplicationController
68
74
  # At view method `products` allows you access to the colelction
69
75
  # No any @'s anymore!
70
76
  def products
71
- @products ||= repo.all
77
+ @products ||= query.all
72
78
  end
73
79
 
74
- # Declaration if repo object:
80
+ # Declaration of repo object:
75
81
  def repo
76
82
  @products_repo ||= ProductRepo.new
77
83
  end
84
+
85
+ # Declaration of query object:
86
+ def query
87
+ @product_query ||= ProductQuery.new
88
+ end
78
89
  # By default repositor will try to find `Product` model and communicate with it
79
90
  # if you need specify other model, pass in params
80
- # ProductRepo.new(model: SaleProduct)
91
+ # ProductRepo.new(model: TopProduct)
92
+ # or
93
+ # ProductQuery.new(model: SaleProduct)
81
94
  end
82
95
  ```
83
96
 
@@ -89,17 +102,18 @@ end
89
102
 
90
103
  **Or manually:**
91
104
 
92
- In `app` directory you need to create new `repos` directory . Recomended to create `application_repo.rb` and inherit from it all repos, so you could keep all your repos under single point of inheritance.
105
+ In `app` directory you need to create new `repos` and `queries` directory . Recomended to create `application_repo.rb` and inherit from it all repos, so you could keep all your repos under single point of inheritance. (Same for queries)
93
106
 
107
+ `app/repos/application_repo.rb`
94
108
  ```ruby
95
- class ApplicationRepo < Repositor::ActiveRecordAdapter
109
+ class ApplicationRepo < Repositor::Repo::ActiveRecordAdapter
96
110
  # now supported only ActiveRecord but will be added more soon
97
111
  #
98
112
  # Adapter allow you to use 4 default methods for CRUD:
99
113
  # :new, :create, :update, :destroy
100
114
  #
101
- # Only 2 for finding/quering records
102
- # :find, :all
115
+ # Only 1 for find record
116
+ # :find
103
117
  #
104
118
  # And additional helpers
105
119
  # find_or_initialize(id, friendly: false) => support for friendly_id gem
@@ -108,15 +122,22 @@ class ApplicationRepo < Repositor::ActiveRecordAdapter
108
122
  end
109
123
  ```
110
124
 
111
- Than you need to create `product_repo.rb`:
125
+ `app/queries/application_query.rb`
126
+ ```ruby
127
+ class ApplicationQuery < Repositor::Query::ActiveRecordAdapter
128
+ # now supported only ActiveRecord but will be added more soon
129
+ #
130
+ # Adapter allow you to use 3 methods for CRUD:
131
+ # :all, :first, :last
132
+ end
133
+ ```
134
+
135
+ Than you need to create `app/repos/product_repo.rb`:
112
136
  ```ruby
113
137
  class ProductRepo < ApplicationRepo
114
138
  # here you have default methods for repository actions
115
139
  # if you want communicate with model class,
116
140
  # just can use model method to send it any method you need
117
- def create_if(params, condition)
118
- create(params) if condition
119
- end
120
141
 
121
142
  # Very good approach is that you got a place where you can
122
143
  # control persistence process, define some logic and reuse it everywhere.
@@ -126,12 +147,30 @@ class ProductRepo < ApplicationRepo
126
147
  if result
127
148
  # trigger some event
128
149
  end
150
+
151
+ result # don't forgot return object
152
+ end
153
+ end
154
+ ```
155
+
156
+ and `app/queries/product_query.rb`
157
+ ```ruby
158
+ class ProductQuery < ApplicationQuery
159
+ # here you can define all scopes
160
+ # ATTENTION! Your queries always must reutrn Relation (!!!)
161
+
162
+ # Simple scopes extraction from model
163
+ def active
164
+ where(status: 'active')
129
165
  end
130
166
 
131
- # You also can compose queries
132
- # But recommended to extract such methods to QueryObject (aka finder)
133
- def all_with_name_john
134
- model.where(name: 'John')
167
+ def disabled(status: 'disabled')
168
+ where(status: 'active')
169
+ end
170
+
171
+ # You can combine queries
172
+ def active_and_disabled
173
+ active | disabled
135
174
  end
136
175
  end
137
176
  ```
@@ -1,8 +1,14 @@
1
1
  class ReposGenerator < Rails::Generators::Base
2
2
  def create_repos_file
3
3
  create_file "app/repos/application_repo.rb",
4
- "class ApplicationRepo
5
- include Repositor::ActiveRecord
4
+ "class ApplicationRepo < Repositor::Repo::ActiveRecordAdapter
5
+ end
6
+ "
7
+ end
8
+
9
+ def create_query_file
10
+ create_file "app/queries/application_query.rb",
11
+ "class ApplicationQuery < Repositor::Query::ActiveRecordAdapter
6
12
  end
7
13
  "
8
14
  end
@@ -1,4 +1,9 @@
1
- require 'repositor/active_record'
1
+ require 'repositor/base'
2
+
3
+ require 'repositor/repo/active_record'
4
+ require 'repositor/repo/instance_allow'
5
+
6
+ require 'repositor/query/active_record'
2
7
 
3
8
  module Repositor
4
9
  end
@@ -0,0 +1,11 @@
1
+ require 'active_support/inflector'
2
+
3
+ module Repositor
4
+ class Base
5
+ attr_reader :model
6
+
7
+ def initialize(model: nil)
8
+ @model = model || self.class.to_s.chomp(self.class::TYPE).singularize.constantize
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+
3
+ module Repositor::Query
4
+ class ActiveRecordAdapter < Repositor::Base
5
+ TYPE = 'Query'.freeze
6
+
7
+ delegate :all, :first, :last, to: :model
8
+ end
9
+ end
@@ -1,18 +1,13 @@
1
1
  require 'active_support/core_ext/module/delegation'
2
- require 'active_support/inflector'
3
- require 'repositor/instance_allow'
2
+ require 'repositor/repo/instance_allow'
4
3
 
5
- module Repositor
6
- class ActiveRecordAdapter
4
+ module Repositor::Repo
5
+ class ActiveRecordAdapter < Repositor::Base
7
6
  extend InstanceMethodsFilter
8
7
 
9
- attr_reader :model
8
+ TYPE = 'Repo'.freeze
10
9
 
11
- delegate :find, :all, :new, :create, :update, :destroy, to: :model
12
-
13
- def initialize(model: nil)
14
- @model = model || self.class.to_s.chomp("Repo").singularize.constantize
15
- end
10
+ delegate :find, :new, :create, :update, :destroy, to: :model
16
11
 
17
12
  # Common find process with supporting of friendly_id params
18
13
  def find_or_initialize(id, friendly: false)
@@ -1,4 +1,4 @@
1
- module Repositor
1
+ module Repositor::Repo
2
2
  module InstanceMethodsFilter
3
3
  attr_reader :allowed_methods
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: repositor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Volodya Sveredyuk
@@ -73,8 +73,10 @@ files:
73
73
  - README.md
74
74
  - lib/generators/repos_generator.rb
75
75
  - lib/repositor.rb
76
- - lib/repositor/active_record.rb
77
- - lib/repositor/instance_allow.rb
76
+ - lib/repositor/base.rb
77
+ - lib/repositor/query/active_record.rb
78
+ - lib/repositor/repo/active_record.rb
79
+ - lib/repositor/repo/instance_allow.rb
78
80
  homepage: https://github.com/sveredyuk/repositor
79
81
  licenses:
80
82
  - MIT