clowne 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +11 -51
- data/.travis.yml +11 -23
- data/Gemfile +9 -9
- data/README.md +8 -7
- data/Rakefile +3 -3
- data/clowne.gemspec +14 -8
- data/docs/.nojekyll +0 -0
- data/docs/.rubocop.yml +8 -2
- data/docs/CNAME +1 -0
- data/docs/README.md +131 -0
- data/docs/_sidebar.md +25 -0
- data/docs/active_record.md +2 -5
- data/docs/after_clone.md +3 -6
- data/docs/after_persist.md +7 -10
- data/docs/architecture.md +2 -5
- data/docs/assets/docsify.min.js +1 -0
- data/docs/assets/prism-ruby.min.js +1 -0
- data/docs/assets/styles.css +348 -0
- data/docs/assets/vue.css +1 -0
- data/docs/clone_mapper.md +2 -5
- data/docs/customization.md +1 -4
- data/docs/exclude_association.md +1 -4
- data/docs/finalize.md +4 -8
- data/docs/from_v02_to_v1.md +2 -10
- data/docs/getting_started.md +171 -0
- data/docs/implicit_cloner.md +1 -4
- data/docs/include_association.md +3 -6
- data/docs/index.html +29 -0
- data/docs/init_as.md +4 -8
- data/docs/inline_configuration.md +1 -4
- data/docs/nullify.md +1 -5
- data/docs/operation.md +3 -6
- data/docs/parameters.md +5 -8
- data/docs/sequel.md +1 -4
- data/docs/supported_adapters.md +3 -6
- data/docs/testing.md +18 -21
- data/docs/traits.md +1 -4
- data/gemfiles/activerecord42.gemfile +5 -5
- data/gemfiles/jruby.gemfile +6 -6
- data/gemfiles/railsmaster.gemfile +6 -6
- data/lib/clowne.rb +11 -11
- data/lib/clowne/adapters/active_record.rb +3 -3
- data/lib/clowne/adapters/active_record/associations.rb +7 -7
- data/lib/clowne/adapters/active_record/associations/base.rb +1 -1
- data/lib/clowne/adapters/active_record/associations/belongs_to.rb +1 -1
- data/lib/clowne/adapters/active_record/associations/has_one.rb +1 -1
- data/lib/clowne/adapters/active_record/resolvers/association.rb +1 -1
- data/lib/clowne/adapters/base.rb +6 -6
- data/lib/clowne/adapters/sequel.rb +7 -7
- data/lib/clowne/adapters/sequel/associations.rb +6 -6
- data/lib/clowne/adapters/sequel/associations/base.rb +2 -2
- data/lib/clowne/adapters/sequel/associations/many_to_many.rb +4 -4
- data/lib/clowne/adapters/sequel/associations/one_to_many.rb +1 -1
- data/lib/clowne/adapters/sequel/associations/one_to_one.rb +1 -1
- data/lib/clowne/adapters/sequel/operation.rb +3 -2
- data/lib/clowne/adapters/sequel/resolvers/after_persist.rb +1 -1
- data/lib/clowne/adapters/sequel/resolvers/association.rb +1 -1
- data/lib/clowne/adapters/sequel/specifications/after_persist_does_not_support.rb +1 -1
- data/lib/clowne/cloner.rb +8 -8
- data/lib/clowne/declarations.rb +15 -15
- data/lib/clowne/declarations/after_clone.rb +1 -1
- data/lib/clowne/declarations/after_persist.rb +1 -1
- data/lib/clowne/declarations/finalize.rb +1 -1
- data/lib/clowne/declarations/include_association.rb +1 -1
- data/lib/clowne/declarations/init_as.rb +1 -1
- data/lib/clowne/declarations/nullify.rb +1 -1
- data/lib/clowne/ext/orm_ext.rb +1 -1
- data/lib/clowne/ext/record_key.rb +1 -1
- data/lib/clowne/ext/string_constantize.rb +1 -1
- data/lib/clowne/ext/yield_self_then.rb +1 -1
- data/lib/clowne/planner.rb +1 -1
- data/lib/clowne/rspec.rb +3 -3
- data/lib/clowne/rspec/clone_association.rb +3 -3
- data/lib/clowne/rspec/clone_associations.rb +2 -2
- data/lib/clowne/rspec/helpers.rb +1 -1
- data/lib/clowne/utils/clone_mapper.rb +1 -1
- data/lib/clowne/utils/operation.rb +3 -3
- data/lib/clowne/utils/params.rb +1 -1
- data/lib/clowne/version.rb +1 -1
- metadata +50 -35
- data/docs/alternatives.md +0 -26
- data/docs/basic_example.md +0 -83
- data/docs/installation.md +0 -46
- data/docs/overview.md +0 -25
- data/docs/web/.gitignore +0 -11
- data/docs/web/README.md +0 -6
- data/docs/web/core/Footer.js +0 -88
- data/docs/web/i18n/en.json +0 -141
- data/docs/web/package.json +0 -14
- data/docs/web/pages/en/help.js +0 -50
- data/docs/web/pages/en/index.js +0 -231
- data/docs/web/pages/en/users.js +0 -47
- data/docs/web/sidebars.json +0 -38
- data/docs/web/siteConfig.js +0 -46
- data/docs/web/static/css/custom.css +0 -235
- data/docs/web/static/fonts/FiraCode-Medium.woff +0 -0
- data/docs/web/static/fonts/FiraCode-Regular.woff +0 -0
- data/docs/web/static/img/favicon/favicon.ico +0 -0
- data/docs/web/yarn.lock +0 -1741
data/docs/sequel.md
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
id: sequel
|
3
|
-
title: Sequel
|
4
|
-
---
|
1
|
+
# Sequel
|
5
2
|
|
6
3
|
Under the hood, Clowne uses Sequel [`NestedAttributes` plugin](http://sequel.jeremyevans.net/rdoc-plugins/classes/Sequel/Plugins/NestedAttributes.html) for cloning source's associations, and you need to configure it.
|
7
4
|
|
data/docs/supported_adapters.md
CHANGED
@@ -1,13 +1,10 @@
|
|
1
|
-
|
2
|
-
id: supported_adapters
|
3
|
-
title: Supported Adapters
|
4
|
-
---
|
1
|
+
# Supported Adapters
|
5
2
|
|
6
3
|
Clowne supports the following ORM adapters (and associations):
|
7
4
|
|
8
5
|
Adapter |1:1 | 1:M | M:M |
|
9
6
|
---------------------------------------------------|------------|-------------|-------------------------|
|
10
|
-
[:active_record](
|
11
|
-
[:sequel](
|
7
|
+
[:active_record](active_record) | has_one | has_many | has_and_belongs_to_many |
|
8
|
+
[:sequel](sequel) | one_to_one | one_to_many | many_to_many |
|
12
9
|
|
13
10
|
For more information see the corresponding adapter documentation.
|
data/docs/testing.md
CHANGED
@@ -1,7 +1,4 @@
|
|
1
|
-
|
2
|
-
id: testing
|
3
|
-
title: Testing
|
4
|
-
---
|
1
|
+
# Testing
|
5
2
|
|
6
3
|
Clowne provides specific tools to help you test your cloners.
|
7
4
|
|
@@ -52,7 +49,7 @@ class UserCloner < Clowne::Cloner
|
|
52
49
|
|
53
50
|
trait :with_popular_posts do
|
54
51
|
include_association :posts, (lambda do |params|
|
55
|
-
where(
|
52
|
+
where("rating > ?", params[:min_rating])
|
56
53
|
end)
|
57
54
|
end
|
58
55
|
end
|
@@ -62,7 +59,7 @@ class PostCloner < Clowne::Cloner
|
|
62
59
|
include_association :comments
|
63
60
|
|
64
61
|
trait :mark_as_copy do |_, record|
|
65
|
-
record.title +=
|
62
|
+
record.title += " (copy)"
|
66
63
|
end
|
67
64
|
end
|
68
65
|
```
|
@@ -74,7 +71,7 @@ Currently, only [RSpec](http://rspec.info/) is supported.
|
|
74
71
|
Add this line to your `spec_helper.rb` (or `rails_helper.rb`):
|
75
72
|
|
76
73
|
```ruby
|
77
|
-
require
|
74
|
+
require "clowne/rspec"
|
78
75
|
```
|
79
76
|
|
80
77
|
## Configuration matchers
|
@@ -151,47 +148,47 @@ Most of the time these actions don't depend on each other, thus we can test them
|
|
151
148
|
```ruby
|
152
149
|
# spec/cloners/user_cloner_spec.rb
|
153
150
|
RSpec.describe UserCloner, type: :cloner do
|
154
|
-
subject(:user) { create :user, name:
|
151
|
+
subject(:user) { create :user, name: "Bombon" }
|
155
152
|
|
156
|
-
specify
|
153
|
+
specify "simple case" do
|
157
154
|
# apply only the specified part of the plan
|
158
155
|
cloned_user = described_class.partial_apply(:nullify, user).to_record
|
159
156
|
expect(cloned_user.email).to be_nil
|
160
157
|
# finalize wasn't applied
|
161
|
-
expect(cloned_user.name).to eq
|
158
|
+
expect(cloned_user.name).to eq "Bombon"
|
162
159
|
end
|
163
160
|
|
164
|
-
specify
|
165
|
-
cloned_user = described_class.partial_apply(:finalize, user, name:
|
161
|
+
specify "with params" do
|
162
|
+
cloned_user = described_class.partial_apply(:finalize, user, name: "new name").to_record
|
166
163
|
# nullify actions were not applied!
|
167
164
|
expect(cloned_user.email).to eq user.email
|
168
165
|
# finalize was applied
|
169
|
-
expect(cloned_user.name).to eq
|
166
|
+
expect(cloned_user.name).to eq "new name"
|
170
167
|
end
|
171
168
|
|
172
|
-
specify
|
173
|
-
a_user = create(:user, name:
|
169
|
+
specify "with traits" do
|
170
|
+
a_user = create(:user, name: "Dindon")
|
174
171
|
cloned_user = described_class.partial_apply(
|
175
172
|
:init_as, user, traits: :copy, target: a_user
|
176
173
|
).to_record
|
177
174
|
# returned user is the same as target
|
178
175
|
expect(cloned_user).to be_eql(a_user)
|
179
|
-
expect(cloned_user.name).to eq
|
176
|
+
expect(cloned_user.name).to eq "Bombon"
|
180
177
|
end
|
181
178
|
|
182
|
-
specify
|
183
|
-
create(:post, user: user, rating: 1, text:
|
184
|
-
create(:post, user: user, rating: 2, text:
|
179
|
+
specify "associations" do
|
180
|
+
create(:post, user: user, rating: 1, text: "Boom Boom")
|
181
|
+
create(:post, user: user, rating: 2, text: "Flying Dumplings")
|
185
182
|
|
186
183
|
# you can specify which associations to include (you can use array)
|
187
184
|
# to apply all associations write:
|
188
185
|
# plan.apply(:association)
|
189
186
|
cloned_user = described_class.partial_apply(
|
190
|
-
|
187
|
+
"association.posts", user, traits: :with_popular_posts, min_rating: 1
|
191
188
|
).to_record
|
192
189
|
|
193
190
|
expect(cloned_user.posts.size).to eq 1
|
194
|
-
expect(cloned_user.posts.first.text).to eq
|
191
|
+
expect(cloned_user.posts.first.text).to eq "Flying Dumplings"
|
195
192
|
end
|
196
193
|
end
|
197
194
|
```
|
data/docs/traits.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
gem
|
5
|
+
gem "activerecord", "~> 4.2"
|
6
|
+
gem "sequel", ">= 5.0"
|
7
|
+
gem "sqlite3", "~> 1.3.13"
|
8
8
|
|
9
|
-
gemspec path:
|
9
|
+
gemspec path: ".."
|
data/gemfiles/jruby.gemfile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
gem
|
8
|
-
gem
|
5
|
+
gem "activerecord-jdbcsqlite3-adapter", "~> 50.0"
|
6
|
+
gem "jdbc-sqlite3"
|
7
|
+
gem "activerecord", "~> 5.0.0"
|
8
|
+
gem "sequel", ">= 5.0"
|
9
9
|
|
10
|
-
gemspec path:
|
10
|
+
gemspec path: ".."
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
source
|
3
|
+
source "https://rubygems.org"
|
4
4
|
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
gem
|
8
|
-
gem
|
5
|
+
gem "arel", github: "rails/arel"
|
6
|
+
gem "rails", github: "rails/rails"
|
7
|
+
gem "sequel", github: "jeremyevans/sequel"
|
8
|
+
gem "sqlite3"
|
9
9
|
|
10
|
-
gemspec path:
|
10
|
+
gemspec path: ".."
|
data/lib/clowne.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require "clowne/version"
|
4
|
+
require "clowne/declarations"
|
5
|
+
require "clowne/cloner"
|
6
6
|
|
7
|
-
require
|
7
|
+
require "clowne/adapters/base"
|
8
8
|
|
9
9
|
# Declarative models cloning
|
10
10
|
module Clowne
|
11
11
|
# List of built-in adapters
|
12
|
-
# rubocop:disable AlignHash
|
12
|
+
# rubocop:disable Layout/AlignHash
|
13
13
|
ADAPTERS = {
|
14
|
-
base:
|
15
|
-
active_record:
|
16
|
-
sequel:
|
14
|
+
base: "Base",
|
15
|
+
active_record: "ActiveRecord",
|
16
|
+
sequel: "Sequel",
|
17
17
|
}.freeze
|
18
|
-
# rubocop:enable AlignHash
|
18
|
+
# rubocop:enable Layout/AlignHash
|
19
19
|
|
20
20
|
class << self
|
21
21
|
attr_reader :default_adapter, :raise_on_override
|
@@ -40,5 +40,5 @@ module Clowne
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
require
|
44
|
-
require
|
43
|
+
require "clowne/adapters/active_record" if defined?(::ActiveRecord)
|
44
|
+
require "clowne/adapters/sequel" if defined?(::Sequel)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "clowne/ext/orm_ext"
|
4
4
|
|
5
5
|
module Clowne
|
6
6
|
module Adapters
|
@@ -13,5 +13,5 @@ ActiveSupport.on_load(:active_record) do
|
|
13
13
|
::ActiveRecord::Base.extend Clowne::Ext::ORMExt
|
14
14
|
end
|
15
15
|
|
16
|
-
require
|
17
|
-
require
|
16
|
+
require "clowne/adapters/active_record/associations"
|
17
|
+
require "clowne/adapters/active_record/resolvers/association"
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
3
|
+
require "clowne/adapters/active_record/associations/base"
|
4
|
+
require "clowne/adapters/active_record/associations/noop"
|
5
|
+
require "clowne/adapters/active_record/associations/belongs_to"
|
6
|
+
require "clowne/adapters/active_record/associations/has_one"
|
7
|
+
require "clowne/adapters/active_record/associations/has_many"
|
8
|
+
require "clowne/adapters/active_record/associations/has_and_belongs_to_many"
|
9
9
|
|
10
10
|
module Clowne
|
11
11
|
module Adapters # :nodoc: all
|
@@ -15,7 +15,7 @@ module Clowne
|
|
15
15
|
belongs_to: BelongsTo,
|
16
16
|
has_one: HasOne,
|
17
17
|
has_many: HasMany,
|
18
|
-
has_and_belongs_to_many: HABTM
|
18
|
+
has_and_belongs_to_many: HABTM,
|
19
19
|
}.freeze
|
20
20
|
|
21
21
|
# Returns an association cloner class for reflection
|
@@ -14,7 +14,7 @@ module Clowne
|
|
14
14
|
|
15
15
|
if reflection.nil?
|
16
16
|
raise UnknownAssociation,
|
17
|
-
|
17
|
+
"Association #{declaration.name} couldn't be found for #{source.class}"
|
18
18
|
end
|
19
19
|
|
20
20
|
cloner_class = Associations.cloner_for(reflection)
|
data/lib/clowne/adapters/base.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "clowne/adapters/registry"
|
4
4
|
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
5
|
+
require "clowne/resolvers/init_as"
|
6
|
+
require "clowne/resolvers/nullify"
|
7
|
+
require "clowne/resolvers/finalize"
|
8
|
+
require "clowne/resolvers/after_persist"
|
9
|
+
require "clowne/resolvers/after_clone"
|
10
10
|
|
11
11
|
module Clowne
|
12
12
|
module Adapters
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "clowne/ext/orm_ext"
|
4
4
|
|
5
5
|
module Clowne
|
6
6
|
module Adapters
|
@@ -21,9 +21,9 @@ end
|
|
21
21
|
|
22
22
|
::Sequel::Model.extend Clowne::Ext::ORMExt
|
23
23
|
|
24
|
-
require
|
25
|
-
require
|
26
|
-
require
|
27
|
-
require
|
28
|
-
require
|
29
|
-
require
|
24
|
+
require "clowne/adapters/sequel/operation"
|
25
|
+
require "clowne/adapters/sequel/associations"
|
26
|
+
require "clowne/adapters/sequel/copier"
|
27
|
+
require "clowne/adapters/sequel/record_wrapper"
|
28
|
+
require "clowne/adapters/sequel/resolvers/association"
|
29
|
+
require "clowne/adapters/sequel/resolvers/after_persist"
|
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
3
|
+
require "clowne/adapters/sequel/associations/base"
|
4
|
+
require "clowne/adapters/sequel/associations/noop"
|
5
|
+
require "clowne/adapters/sequel/associations/one_to_one"
|
6
|
+
require "clowne/adapters/sequel/associations/one_to_many"
|
7
|
+
require "clowne/adapters/sequel/associations/many_to_many"
|
8
8
|
|
9
9
|
module Clowne
|
10
10
|
module Adapters # :nodoc: all
|
@@ -13,7 +13,7 @@ module Clowne
|
|
13
13
|
SEQUEL_2_CLONER = {
|
14
14
|
one_to_one: OneToOne,
|
15
15
|
one_to_many: OneToMany,
|
16
|
-
many_to_many: ManyToMany
|
16
|
+
many_to_many: ManyToMany,
|
17
17
|
}.freeze
|
18
18
|
|
19
19
|
# Returns an association cloner class for reflection
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "clowne/adapters/base/association"
|
4
4
|
|
5
5
|
module Clowne
|
6
6
|
module Adapters # :nodoc: all
|
@@ -10,7 +10,7 @@ module Clowne
|
|
10
10
|
private
|
11
11
|
|
12
12
|
def init_scope
|
13
|
-
@_init_scope ||= source.__send__([association_name,
|
13
|
+
@_init_scope ||= source.__send__([association_name, "dataset"].join("_"))
|
14
14
|
end
|
15
15
|
|
16
16
|
def record_wrapper(record)
|
@@ -7,10 +7,10 @@ module Clowne
|
|
7
7
|
class ManyToMany < Base
|
8
8
|
def call(record)
|
9
9
|
clones = with_scope
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
.lazy
|
11
|
+
.map(&method(:clone_one))
|
12
|
+
.map(&method(:record_wrapper))
|
13
|
+
.to_a
|
14
14
|
|
15
15
|
record_wrapper(record).remember_assoc(:"#{association_name}_attributes", clones)
|
16
16
|
|
@@ -9,7 +9,7 @@ module Clowne
|
|
9
9
|
child = association
|
10
10
|
return record unless child
|
11
11
|
|
12
|
-
warn
|
12
|
+
warn "[Clowne] Has one association does not support scope" unless declaration.scope.nil?
|
13
13
|
|
14
14
|
child_clone = clone_one(child)
|
15
15
|
child_clone[:"#{reflection[:key]}"] = nil
|
@@ -1,13 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "clowne/ext/record_key"
|
4
4
|
|
5
5
|
module Clowne
|
6
6
|
module Adapters
|
7
7
|
class Sequel # :nodoc: all
|
8
8
|
class Operation < Clowne::Utils::Operation
|
9
9
|
include Clowne::Ext::RecordKey
|
10
|
-
|
11
10
|
def initialize(mapper)
|
12
11
|
super
|
13
12
|
@records = {}
|
@@ -24,6 +23,8 @@ module Clowne
|
|
24
23
|
def to_record
|
25
24
|
return @_record if defined?(@_record)
|
26
25
|
|
26
|
+
record_wrapper(@clone)
|
27
|
+
|
27
28
|
@_record = @records[key(@clone)].to_model.tap do
|
28
29
|
run_after_clone
|
29
30
|
end
|