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