clowne 1.4.0 → 1.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +0 -2
- data/lib/clowne/adapters/active_record/associations/noop.rb +1 -1
- data/lib/clowne/adapters/base/association.rb +1 -1
- data/lib/clowne/adapters/sequel/associations/one_to_many.rb +0 -4
- data/lib/clowne/ext/record_key.rb +1 -1
- data/lib/clowne/version.rb +1 -1
- metadata +7 -113
- data/.codeclimate.yml +0 -7
- data/.gitattributes +0 -1
- data/.github/workflows/rspec-jruby.yml +0 -33
- data/.github/workflows/rspec-truffle.yml +0 -35
- data/.github/workflows/rspec.yml +0 -51
- data/.github/workflows/rubocop.yml +0 -20
- data/.gitignore +0 -16
- data/.rspec +0 -3
- data/.rubocop.yml +0 -29
- data/.rufo +0 -3
- data/Gemfile +0 -20
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/clowne.gemspec +0 -36
- data/docs/.nojekyll +0 -0
- data/docs/.rubocop.yml +0 -15
- data/docs/CNAME +0 -1
- data/docs/README.md +0 -131
- data/docs/_sidebar.md +0 -25
- data/docs/active_record.md +0 -33
- data/docs/after_clone.md +0 -53
- data/docs/after_persist.md +0 -77
- data/docs/architecture.md +0 -138
- data/docs/assets/docsify.min.js +0 -1
- data/docs/assets/prism-ruby.min.js +0 -1
- data/docs/assets/styles.css +0 -348
- data/docs/assets/vue.css +0 -1
- data/docs/clone_mapper.md +0 -59
- data/docs/customization.md +0 -63
- data/docs/exclude_association.md +0 -61
- data/docs/finalize.md +0 -31
- data/docs/from_v02_to_v1.md +0 -83
- data/docs/getting_started.md +0 -171
- data/docs/implicit_cloner.md +0 -33
- data/docs/include_association.md +0 -133
- data/docs/index.html +0 -29
- data/docs/init_as.md +0 -40
- data/docs/inline_configuration.md +0 -37
- data/docs/nullify.md +0 -33
- data/docs/operation.md +0 -55
- data/docs/parameters.md +0 -112
- data/docs/sequel.md +0 -50
- data/docs/supported_adapters.md +0 -10
- data/docs/testing.md +0 -194
- data/docs/traits.md +0 -25
- data/gemfiles/activerecord42.gemfile +0 -9
- data/gemfiles/jruby.gemfile +0 -10
- data/gemfiles/railsmaster.gemfile +0 -10
- data/lib/clowne/ext/yield_self_then.rb +0 -25
data/docs/testing.md
DELETED
@@ -1,194 +0,0 @@
|
|
1
|
-
# Testing
|
2
|
-
|
3
|
-
Clowne provides specific tools to help you test your cloners.
|
4
|
-
|
5
|
-
The main goal is to make it possible to test different cloning phases separately and avoid _heavy_ tests setup phases.
|
6
|
-
|
7
|
-
Let's consider the following models and cloners:
|
8
|
-
|
9
|
-
```ruby
|
10
|
-
# app/models/user.rb
|
11
|
-
class User < ApplicationRecord
|
12
|
-
has_one :profile
|
13
|
-
has_many :posts
|
14
|
-
end
|
15
|
-
|
16
|
-
# app/models/post.rb
|
17
|
-
class Post < ApplicationRecord
|
18
|
-
has_many :comments
|
19
|
-
has_many :votes
|
20
|
-
|
21
|
-
scope :draft, -> { where(draft: true) }
|
22
|
-
end
|
23
|
-
|
24
|
-
# app/cloners/user_cloner.rb
|
25
|
-
class UserCloner < Clowne::Cloner
|
26
|
-
class ProfileCloner
|
27
|
-
nullify :rating
|
28
|
-
end
|
29
|
-
|
30
|
-
include_association :profile, clone_with: ProfileCloner
|
31
|
-
|
32
|
-
nullify :email
|
33
|
-
|
34
|
-
finalize do |_, record, name: nil, **|
|
35
|
-
record.name = name unless name.nil?
|
36
|
-
end
|
37
|
-
|
38
|
-
trait :copy do
|
39
|
-
init_as do |user, target:, **|
|
40
|
-
# copy name
|
41
|
-
target.name = user.name
|
42
|
-
target
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
trait :with_posts do
|
47
|
-
include_association :posts, :draft, traits: :mark_as_copy
|
48
|
-
end
|
49
|
-
|
50
|
-
trait :with_popular_posts do
|
51
|
-
include_association :posts, (lambda do |params|
|
52
|
-
where("rating > ?", params[:min_rating])
|
53
|
-
end)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# app/cloners/post_cloner.rb
|
58
|
-
class PostCloner < Clowne::Cloner
|
59
|
-
include_association :comments
|
60
|
-
|
61
|
-
trait :mark_as_copy do |_, record|
|
62
|
-
record.title += " (copy)"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
```
|
66
|
-
|
67
|
-
## Getting started
|
68
|
-
|
69
|
-
Currently, only [RSpec](http://rspec.info/) is supported.
|
70
|
-
|
71
|
-
Add this line to your `spec_helper.rb` (or `rails_helper.rb`):
|
72
|
-
|
73
|
-
```ruby
|
74
|
-
require "clowne/rspec"
|
75
|
-
```
|
76
|
-
|
77
|
-
## Configuration matchers
|
78
|
-
|
79
|
-
There are several matchers that allow you to verify the cloner configuration.
|
80
|
-
|
81
|
-
### `clone_associations`
|
82
|
-
|
83
|
-
This matcher vefifies that your cloner includes the specified associations:
|
84
|
-
|
85
|
-
```ruby
|
86
|
-
# spec/cloners/user_cloner_spec.rb
|
87
|
-
RSpec.describe UserCloner, type: :cloner do
|
88
|
-
subject { described_class }
|
89
|
-
|
90
|
-
specify do
|
91
|
-
# checks that only the specified associations is included
|
92
|
-
is_expected.to clone_associations(:profile)
|
93
|
-
|
94
|
-
# with traits
|
95
|
-
is_expected.to clone_associations(:profile, :posts)
|
96
|
-
.with_traits(:with_posts)
|
97
|
-
|
98
|
-
# raises when there are some unspecified associations
|
99
|
-
is_expected.to clone_associations(:profile)
|
100
|
-
.with_traits(:with_posts)
|
101
|
-
#=> raises RSpec::Expectations::ExpectationNotMetError
|
102
|
-
end
|
103
|
-
end
|
104
|
-
```
|
105
|
-
|
106
|
-
### `clone_association`
|
107
|
-
|
108
|
-
This matcher allows to verify the specified association options:
|
109
|
-
|
110
|
-
```ruby
|
111
|
-
# spec/cloners/user_cloner_spec.rb
|
112
|
-
RSpec.describe UserCloner, type: :cloner do
|
113
|
-
subject { described_class }
|
114
|
-
|
115
|
-
specify do
|
116
|
-
# simply check that association is included
|
117
|
-
is_expected.to clone_association(:profile)
|
118
|
-
|
119
|
-
# check options
|
120
|
-
is_expected.to clone_association(
|
121
|
-
:profile,
|
122
|
-
clone_with: described_class::ProfileCloner
|
123
|
-
)
|
124
|
-
|
125
|
-
# with traits, scope and activated trait
|
126
|
-
is_expected.to clone_association(
|
127
|
-
:posts,
|
128
|
-
traits: :mark_as_copy,
|
129
|
-
scope: :draft
|
130
|
-
).with_traits(:with_posts)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
```
|
134
|
-
|
135
|
-
**NOTE:** `clone_associations`/`clone_association` matchers are only available in groups marked with `type: :cloner` tag.
|
136
|
-
|
137
|
-
Clowne automaticaly marks all specs in `spec/cloners` folder with `type: :cloner`. Otherwise you have to add this tag you.
|
138
|
-
|
139
|
-
|
140
|
-
## Using partial cloning
|
141
|
-
|
142
|
-
Under the hood, Clowne builds a [compilation plan](architecture.md) which is used to clone the record.
|
143
|
-
|
144
|
-
Plan is a set of _actions_ (such as `nullify`, `finalize`, `association`, `init_as`) which are applied to the record.
|
145
|
-
|
146
|
-
Most of the time these actions don't depend on each other, thus we can test them separately:
|
147
|
-
|
148
|
-
```ruby
|
149
|
-
# spec/cloners/user_cloner_spec.rb
|
150
|
-
RSpec.describe UserCloner, type: :cloner do
|
151
|
-
subject(:user) { create :user, name: "Bombon" }
|
152
|
-
|
153
|
-
specify "simple case" do
|
154
|
-
# apply only the specified part of the plan
|
155
|
-
cloned_user = described_class.partial_apply(:nullify, user).to_record
|
156
|
-
expect(cloned_user.email).to be_nil
|
157
|
-
# finalize wasn't applied
|
158
|
-
expect(cloned_user.name).to eq "Bombon"
|
159
|
-
end
|
160
|
-
|
161
|
-
specify "with params" do
|
162
|
-
cloned_user = described_class.partial_apply(:finalize, user, name: "new name").to_record
|
163
|
-
# nullify actions were not applied!
|
164
|
-
expect(cloned_user.email).to eq user.email
|
165
|
-
# finalize was applied
|
166
|
-
expect(cloned_user.name).to eq "new name"
|
167
|
-
end
|
168
|
-
|
169
|
-
specify "with traits" do
|
170
|
-
a_user = create(:user, name: "Dindon")
|
171
|
-
cloned_user = described_class.partial_apply(
|
172
|
-
:init_as, user, traits: :copy, target: a_user
|
173
|
-
).to_record
|
174
|
-
# returned user is the same as target
|
175
|
-
expect(cloned_user).to be_eql(a_user)
|
176
|
-
expect(cloned_user.name).to eq "Bombon"
|
177
|
-
end
|
178
|
-
|
179
|
-
specify "associations" do
|
180
|
-
create(:post, user: user, rating: 1, text: "Boom Boom")
|
181
|
-
create(:post, user: user, rating: 2, text: "Flying Dumplings")
|
182
|
-
|
183
|
-
# you can specify which associations to include (you can use array)
|
184
|
-
# to apply all associations write:
|
185
|
-
# plan.apply(:association)
|
186
|
-
cloned_user = described_class.partial_apply(
|
187
|
-
"association.posts", user, traits: :with_popular_posts, min_rating: 1
|
188
|
-
).to_record
|
189
|
-
|
190
|
-
expect(cloned_user.posts.size).to eq 1
|
191
|
-
expect(cloned_user.posts.first.text).to eq "Flying Dumplings"
|
192
|
-
end
|
193
|
-
end
|
194
|
-
```
|
data/docs/traits.md
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# Traits
|
2
|
-
|
3
|
-
Traits allow you to group cloner declarations together and then apply them (like in [`factory_bot`](https://github.com/thoughtbot/factory_bot)):
|
4
|
-
|
5
|
-
```ruby
|
6
|
-
class UserCloner < Clowne::Cloner
|
7
|
-
trait :with_posts do
|
8
|
-
include_association :posts
|
9
|
-
end
|
10
|
-
|
11
|
-
trait :with_profile do
|
12
|
-
include_association :profile
|
13
|
-
end
|
14
|
-
|
15
|
-
trait :nullify_name do
|
16
|
-
nullify :name
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
UserCloner.call(user, traits: %i[with_posts with_profile nullify_name])
|
21
|
-
# or
|
22
|
-
UserCloner.call(user, traits: :nullify_name)
|
23
|
-
# or
|
24
|
-
# ...
|
25
|
-
```
|
data/gemfiles/jruby.gemfile
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Clowne
|
4
|
-
module Ext # :nodoc: all
|
5
|
-
# Add yield_self and then if missing
|
6
|
-
module YieldSelfThen
|
7
|
-
module Ext
|
8
|
-
unless nil.respond_to?(:yield_self)
|
9
|
-
def yield_self
|
10
|
-
yield self
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
alias_method :then, :yield_self
|
15
|
-
end
|
16
|
-
|
17
|
-
# See https://github.com/jruby/jruby/issues/5220
|
18
|
-
::Object.include(Ext) if RUBY_PLATFORM.match?(/java/i)
|
19
|
-
|
20
|
-
refine Object do
|
21
|
-
include Ext
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|