clowne 0.1.0.beta1 → 0.1.0.pre1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d56daf439132f64870a49326ff8afe5465691b7
4
- data.tar.gz: b273e7e236eee799de5a5ea7386c05d26a173b04
3
+ metadata.gz: b833f076ba69c9b626d4038e977e4a40d8de8dbb
4
+ data.tar.gz: 271303497d931c2773c8c4f948baacfa9819cd4a
5
5
  SHA512:
6
- metadata.gz: d55650b452063d8eeadbcc3c4a2c1c648c3b5d7c18905ac2d0f7dee05e734358dd19798f7382b284676b693628dcde4fb237e937ce0fafd68f4b2ba860c183fd
7
- data.tar.gz: 35463db710e77b7320ff114d1b1fd011ccf9d7405216565420b885ee9b989be8ce734b17ec7c3dbd07017326a1921b0fe4632afff141603f2b41520cce60d238
6
+ metadata.gz: f4df02c8872ecdc0b1f70fd74a12549065aaf85cd6922b2648043905f3eba9d4bf415716a11b5f0a8f458d7c59d11edbe590e2e1c92f3328887ab9da38c7de1b
7
+ data.tar.gz: '0683a5756b9797ac8c2a9cd60a4adbd29c214b9dbd55ef3fd736e2e05b414a7b0d92493edcde7e9a109434ceb67ca557cc55953ec08f1caad2a2c35e13ac1439'
@@ -14,10 +14,6 @@ Rails:
14
14
  Naming/AccessorMethodName:
15
15
  Enabled: false
16
16
 
17
- Naming/ClassAndModuleCamelCase:
18
- Exclude:
19
- - 'spec/**/*.rb'
20
-
21
17
  Style/TrivialAccessors:
22
18
  Enabled: false
23
19
 
@@ -1,8 +1,6 @@
1
1
  # Change log
2
2
 
3
- ## master
4
-
5
- ## 0.1.0.beta1 (2018-01-08)
3
+ ## master branch
6
4
 
7
5
  - Initial version. ([@ssnickolay][], [@palkan][])
8
6
 
data/README.md CHANGED
@@ -1,10 +1,11 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/clowne.svg)](https://badge.fury.io/rb/clowne)
2
2
  [![Build Status](https://travis-ci.org/palkan/clowne.svg?branch=master)](https://travis-ci.org/palkan/clowne)
3
+ [![Code Climate](https://codeclimate.com/github/palkan/clowne.svg)](https://codeclimate.com/github/palkan/clowne)
3
4
  [![Test Coverage](https://codeclimate.com/github/palkan/clowne/badges/coverage.svg)](https://codeclimate.com/github/palkan/clowne/coverage)
4
5
 
5
6
  # Clowne
6
7
 
7
- **NOTE**: this is the documentation for pre-release version **0.1.0.beta1**.
8
+ **NOTICE**: gem is currently under heavy development, we plan to release the first version 'till the end of the year.
8
9
 
9
10
  A flexible gem for cloning your models. Clowne focuses on ease of use and provides the ability to connect various ORM adapters (currently only ActiveRecord is supported).
10
11
 
@@ -64,7 +65,7 @@ class UserCloner < Clowne::Cloner
64
65
  include_association :posts
65
66
 
66
67
  nullify :login
67
-
68
+
68
69
  # params here is an arbitrary hash passed into cloner
69
70
  finalize do |_source, record, params|
70
71
  record.email = params[:email]
@@ -81,38 +82,33 @@ end
81
82
  and call it
82
83
 
83
84
  ```ruby
84
- cloned = UserCloner.call(User.last, { email: "fake@example.com" })
85
- cloned.persisted?
85
+ clone = UserCloner.call(User.last, { email: "fake@example.com" })
86
+ clone.persisted?
86
87
  # => false
87
- cloned.save!
88
- cloned.login
88
+ clone.save!
89
+ clone.login
89
90
  # => nil
90
- cloned.email
91
+ clone.email
91
92
  # => "fake@example.com"
92
93
 
93
94
  # associations:
94
- cloned.posts.count == User.last.posts.count
95
+ clone.posts.count == User.last.posts.count
95
96
  # => true
96
- cloned.profile.name
97
+ clone.profile.name
97
98
  # => nil
98
99
  ```
99
100
 
100
101
  ## <a name="features">Features
101
102
 
102
103
  - [Configuration](#configuration)
103
- - [Include association](#include_association)
104
- - - [Inline configuration](#config-inline)
105
104
  - [Include one association](#include_association)
106
105
  - - [Scope](#include_association_scope)
107
106
  - - [Options](#include_association_options)
108
- - - [Multiple associations](#include_associations)
109
107
  - [Exclude association](#exclude_association)
110
- - - [Multiple associations](#exclude_associations)
111
108
  - [Nullify attribute(s)](#nullify)
112
109
  - [Execute finalize block](#finalize)
113
110
  - [Traits](#traits)
114
111
  - [Execution order](#execution_order)
115
- - [ActiveRecord DSL](#ar_dsl)
116
112
  - [Customization](#customization)
117
113
 
118
114
  ### <a name="configuration"></a>Configuration
@@ -124,39 +120,6 @@ You can configure the default adapter for cloners:
124
120
  Clowne.default_adapter = :active_record
125
121
  ```
126
122
 
127
- #### <a name="config-inline"></a>Inline Configuration
128
-
129
- You can also enhance the cloner configuration inline (i.e. add dynamic declarations):
130
-
131
- ```ruby
132
- cloned = UserCloner.call(User.last) do
133
- exclude_association :profile
134
-
135
- finalize do |source, record|
136
- record.email = "clone_of_#{source.email}"
137
- end
138
- end
139
-
140
- cloned.email
141
- # => "clone_of_john@example.com"
142
-
143
- # associations:
144
- cloned.posts.size == User.last.posts.size
145
- # => true
146
- cloned.profile
147
- # => nil
148
- ```
149
-
150
- Inline enhancement doesn't affect the _global_ configuration, so you can use it without any fear.
151
-
152
- Thus it's also possible to clone objects without any cloner classes at all by using `Clowne::Cloner`:
153
-
154
- ```ruby
155
- cloned = Clowne::Cloner.call(user) do
156
- # anything you want!
157
- end
158
- ```
159
-
160
123
  ### <a name="include_association"></a>Include one association
161
124
 
162
125
  Powerful declaration for including model's association.
@@ -260,23 +223,6 @@ UserCloner.call(user)
260
223
 
261
224
  **Notice: if custom cloner is not defined, clowne tries to find default cloner and use it. (PostCloner for previous example)**
262
225
 
263
- #### <a name="include_associations"></a>Include multiple association
264
-
265
- It's possible to include multiple associations at once with default options and scope
266
-
267
- ```ruby
268
- class User < ActiveRecord::Base
269
- has_many :accounts
270
- has_many :posts
271
- end
272
-
273
- class UserCloner < Clowne::Cloner
274
- adapter :active_record
275
-
276
- include_associations :accounts, :posts
277
- end
278
- ```
279
-
280
226
  ### <a name="exclude_association"></a>Exclude association
281
227
 
282
228
  Exclude association from copying
@@ -322,10 +268,6 @@ clone.comments.empty? #=> true
322
268
  Why so? That allows to have deterministic cloning plans when combining multiple traits
323
269
  (or inheriting cloners).
324
270
 
325
- #### <a name="exclude_associations"></a>Exclude multiple association
326
-
327
- It's possible to exclude multiple associations the same way as `include_associations` but with `exclude_associations`
328
-
329
271
  ### <a name="nullify"></a>Nullify attribute(s)
330
272
 
331
273
  Nullify attributes:
@@ -437,38 +379,6 @@ For ActiveRecord:
437
379
  - run `finalize` blocks
438
380
  The order of `finalize` blocks is the order they've been written.
439
381
 
440
- ### <a name="ar_dsl"></a>Active Record DSL
441
-
442
- Clowne provides an optional ActiveRecord integration which allows you to configure cloners in your models and adds a shortcut to invoke cloners (`#clowne` method). (Note: that's exactly the way [`amoeba`](https://github.com/amoeba-rb/amoeba) works).
443
-
444
- To enable this integration you must require `"clowne/adapters/active_record/dsl"` somewhere in your app, e.g. in initializer:
445
-
446
- ```ruby
447
- # config/initializers/clowne.rb
448
- require "clowne/adapters/active_record/dsl"
449
- ```
450
-
451
- Now you can specify cloning configs in your AR models:
452
-
453
- ```ruby
454
- class User < ActiveRecord::Base
455
- clowne_config do
456
- include_associations :profile
457
-
458
- nullify :email
459
-
460
- # whatever available for your cloners,
461
- # active_record adapter is set implicitly here
462
- end
463
- end
464
- ```
465
-
466
- And then you can clone objects like this:
467
-
468
- ```ruby
469
- cloned_user = user.clowne(traits: my_traits, **params)
470
- ```
471
-
472
382
  ### <a name="customization"></a>Customization
473
383
 
474
384
  Clowne is built with extensibility in mind. You can create your own DSL commands and resolvers.
@@ -5,16 +5,10 @@ module Clowne
5
5
  class ActiveRecord
6
6
  module Associations
7
7
  class HasOne < Base
8
- # rubocop: disable Metrics/MethodLength
9
8
  def call(record)
10
9
  child = association
11
10
  return record unless child
12
- unless scope.nil?
13
- warn(
14
- '[Clowne] Has one association does not support scopes ' \
15
- "(#{@association_name} for #{@source.class})"
16
- )
17
- end
11
+ warn '[Clowne] Has one association does not support scopes' unless scope.nil?
18
12
 
19
13
  child_clone = clone_one(child)
20
14
  child_clone[:"#{reflection.foreign_key}"] = nil
@@ -22,7 +16,6 @@ module Clowne
22
16
 
23
17
  record
24
18
  end
25
- # rubocop: enable Metrics/MethodLength
26
19
  end
27
20
  end
28
21
  end
@@ -6,10 +6,7 @@ module Clowne
6
6
  module Associations
7
7
  class Noop < Base
8
8
  def call(record)
9
- warn(
10
- "[Clowne] Reflection #{reflection.class.name} is not supported "\
11
- "(#{@association_name} for #{@source.class})"
12
- )
9
+ warn("[Clowne] Reflection #{reflection.class.name} is not supported")
13
10
  record
14
11
  end
15
12
  end
@@ -38,8 +38,8 @@ module Clowne # :nodoc: all
38
38
  @traits[name].extend_with(block)
39
39
  end
40
40
 
41
- # rubocop: disable Metrics/AbcSize, Metrics/MethodLength
42
- # rubocop: disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
41
+ # rubocop: disable Metrics/AbcSize
42
+ # rubocop: disable Metrics/MethodLength
43
43
  def call(object, **options)
44
44
  raise(UnprocessableSourceError, 'Nil is not cloneable object') if object.nil?
45
45
 
@@ -56,13 +56,11 @@ module Clowne # :nodoc: all
56
56
  plan_with_traits(traits)
57
57
  end
58
58
 
59
- plan = Clowne::Planner.enhance(plan, Proc.new) if block_given?
60
-
61
59
  adapter.clone(object, plan, params: options)
62
60
  end
63
61
 
64
- # rubocop: enable Metrics/AbcSize, Metrics/MethodLength
65
- # rubocop: enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
62
+ # rubocop: enable Metrics/AbcSize
63
+ # rubocop: enable Metrics/MethodLength
66
64
 
67
65
  def default_plan
68
66
  return @default_plan if instance_variable_defined?(:@default_plan)
@@ -11,6 +11,11 @@ module Clowne
11
11
 
12
12
  def compile(plan)
13
13
  plan.remove_from(:association, name)
14
+
15
+ # update all_associations plan
16
+ all_associations = plan.get(:all_associations)
17
+ return if all_associations.nil?
18
+ all_associations.except! name
14
19
  end
15
20
  end
16
21
  end
@@ -16,6 +16,8 @@ module Clowne
16
16
  end
17
17
 
18
18
  def compile(plan)
19
+ # Clear `#include_all`
20
+ plan.remove(:all_associations)
19
21
  plan.add_to(:association, name, self)
20
22
  end
21
23
 
@@ -5,7 +5,10 @@ require 'clowne/plan'
5
5
  module Clowne
6
6
  class Planner # :nodoc: all
7
7
  class << self
8
- # Compile plan for cloner with traits
8
+ # Params:
9
+ # +cloner+:: Cloner object
10
+ # +init_plan+:: Init plan
11
+ # +traits+:: List of traits if any
9
12
  def compile(cloner, traits: nil)
10
13
  declarations = cloner.declarations.dup
11
14
 
@@ -16,16 +19,6 @@ module Clowne
16
19
  end
17
20
  end
18
21
 
19
- # Extend previously compiled plan with an arbitrary block
20
- # NOTE: It doesn't modify the plan itself but return a copy
21
- def enhance(plan, block)
22
- trait = Clowne::Declarations::Trait.new.tap { |t| t.extend_with(block) }
23
-
24
- trait.compiled.each_with_object(plan.dup) do |declaration, new_plan|
25
- declaration.compile(new_plan)
26
- end
27
- end
28
-
29
22
  private
30
23
 
31
24
  def compile_traits(cloner, traits)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Clowne
4
- VERSION = '0.1.0.beta1'
4
+ VERSION = '0.1.0.pre1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: clowne
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.beta1
4
+ version: 0.1.0.pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Dementyev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2018-01-08 00:00:00.000000000 Z
12
+ date: 2018-01-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -114,7 +114,6 @@ files:
114
114
  - lib/clowne/adapters/active_record/associations/has_many.rb
115
115
  - lib/clowne/adapters/active_record/associations/has_one.rb
116
116
  - lib/clowne/adapters/active_record/associations/noop.rb
117
- - lib/clowne/adapters/active_record/dsl.rb
118
117
  - lib/clowne/adapters/base.rb
119
118
  - lib/clowne/adapters/base/finalize.rb
120
119
  - lib/clowne/adapters/base/nullify.rb
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Clowne
4
- module Adapters
5
- # Extend ActiveRecord with Clowne DSL and methods
6
- module ActiveRecordDSL
7
- module InstanceMethods # :nodoc:
8
- # Shortcut to call class's cloner call with self
9
- def clowne(*args)
10
- self.class.cloner_class.call(self, *args)
11
- end
12
- end
13
-
14
- module ClassMethods # :nodoc:
15
- def clowne_config(options = {}, &block)
16
- if options.delete(:inherit) != false && superclass.respond_to?(:cloner_class)
17
- parent_cloner = superclass.cloner_class
18
- end
19
-
20
- parent_cloner ||= Clowne::Cloner
21
- cloner = instance_variable_set(:@_clowne_cloner, Class.new(parent_cloner))
22
- cloner.adapter :active_record
23
- cloner.instance_exec(&block)
24
- end
25
- end
26
- end
27
- end
28
- end
29
-
30
- ActiveSupport.on_load(:active_record) do
31
- ::ActiveRecord::Base.extend Clowne::Adapters::ActiveRecordDSL::ClassMethods
32
- ::ActiveRecord::Base.include Clowne::Adapters::ActiveRecordDSL::InstanceMethods
33
- end