clowne 0.2.0 → 1.0.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/.rubocop.yml +6 -0
- data/.travis.yml +6 -3
- data/CHANGELOG.md +14 -0
- data/Gemfile +1 -1
- data/README.md +30 -9
- data/clowne.gemspec +4 -3
- data/docs/active_record.md +2 -2
- data/docs/after_persist.md +80 -0
- data/docs/basic_example.md +22 -5
- data/docs/clone_mapper.md +62 -0
- data/docs/customization.md +2 -1
- data/docs/exclude_association.md +5 -4
- data/docs/finalize.md +2 -2
- data/docs/from_v02_to_v1.md +91 -0
- data/docs/implicit_cloner.md +1 -1
- data/docs/include_association.md +4 -4
- data/docs/init_as.md +10 -2
- data/docs/inline_configuration.md +4 -2
- data/docs/installation.md +31 -1
- data/docs/nullify.md +2 -2
- data/docs/operation.md +58 -0
- data/docs/overview.md +24 -0
- data/docs/parameters.md +5 -4
- data/docs/sequel.md +15 -18
- data/docs/supported_adapters.md +2 -2
- data/docs/testing.md +7 -5
- data/docs/web/README.md +6 -0
- data/docs/web/core/Footer.js +5 -9
- data/docs/web/i18n/en.json +8 -4
- data/docs/web/pages/en/index.js +1 -1
- data/docs/web/sidebars.json +10 -4
- data/docs/web/siteConfig.js +6 -4
- data/docs/web/static/css/custom.css +16 -10
- data/gemfiles/activerecord42.gemfile +3 -1
- data/gemfiles/jruby.gemfile +2 -0
- data/gemfiles/railsmaster.gemfile +2 -0
- data/lib/clowne.rb +3 -0
- data/lib/clowne/adapters/active_record.rb +2 -3
- data/lib/clowne/adapters/active_record/associations/base.rb +0 -4
- data/lib/clowne/adapters/active_record/associations/has_one.rb +2 -1
- data/lib/clowne/adapters/active_record/resolvers/association.rb +38 -0
- data/lib/clowne/adapters/base.rb +42 -43
- data/lib/clowne/adapters/base/association.rb +24 -15
- data/lib/clowne/adapters/registry.rb +49 -0
- data/lib/clowne/adapters/sequel.rb +10 -6
- data/lib/clowne/adapters/sequel/associations/base.rb +8 -4
- data/lib/clowne/adapters/sequel/associations/many_to_many.rb +6 -2
- data/lib/clowne/adapters/sequel/associations/one_to_many.rb +7 -2
- data/lib/clowne/adapters/sequel/associations/one_to_one.rb +7 -2
- data/lib/clowne/adapters/sequel/operation.rb +32 -0
- data/lib/clowne/adapters/sequel/record_wrapper.rb +0 -16
- data/lib/clowne/adapters/sequel/resolvers/after_persist.rb +22 -0
- data/lib/clowne/adapters/sequel/resolvers/association.rb +51 -0
- data/lib/clowne/adapters/sequel/specifications/after_persist_does_not_support.rb +15 -0
- data/lib/clowne/cloner.rb +27 -20
- data/lib/clowne/declarations.rb +2 -1
- data/lib/clowne/declarations/after_persist.rb +21 -0
- data/lib/clowne/declarations/finalize.rb +1 -0
- data/lib/clowne/declarations/include_association.rb +2 -1
- data/lib/clowne/declarations/init_as.rb +1 -0
- data/lib/clowne/declarations/nullify.rb +1 -0
- data/lib/clowne/declarations/trait.rb +1 -0
- data/lib/clowne/dsl.rb +9 -0
- data/lib/clowne/ext/lambda_as_proc.rb +1 -0
- data/lib/clowne/ext/record_key.rb +12 -0
- data/lib/clowne/ext/yield_self_then.rb +25 -0
- data/lib/clowne/planner.rb +6 -3
- data/lib/clowne/resolvers/after_persist.rb +18 -0
- data/lib/clowne/resolvers/finalize.rb +12 -0
- data/lib/clowne/resolvers/init_as.rb +13 -0
- data/lib/clowne/resolvers/nullify.rb +15 -0
- data/lib/clowne/rspec/helpers.rb +1 -0
- data/lib/clowne/utils/clone_mapper.rb +26 -0
- data/lib/clowne/utils/operation.rb +83 -0
- data/lib/clowne/utils/options.rb +39 -0
- data/lib/clowne/utils/params.rb +64 -0
- data/lib/clowne/utils/plan.rb +90 -0
- data/lib/clowne/version.rb +1 -1
- metadata +44 -18
- data/docs/configuration.md +0 -29
- data/docs/execution_order.md +0 -14
- data/docs/web/static/fonts/StemText.woff +0 -0
- data/docs/web/static/fonts/StemTextBold.woff +0 -0
- data/lib/clowne/adapters/active_record/association.rb +0 -34
- data/lib/clowne/adapters/base/finalize.rb +0 -19
- data/lib/clowne/adapters/base/init_as.rb +0 -21
- data/lib/clowne/adapters/base/nullify.rb +0 -19
- data/lib/clowne/adapters/sequel/association.rb +0 -47
- data/lib/clowne/params.rb +0 -62
- data/lib/clowne/plan.rb +0 -83
    
        data/docs/web/pages/en/index.js
    CHANGED
    
    | @@ -82,7 +82,7 @@ class HomeSplash extends React.Component { | |
| 82 82 | 
             
                    <div className="inner">
         | 
| 83 83 | 
             
                      <ProjectTitle />
         | 
| 84 84 | 
             
                      <PromoSection>
         | 
| 85 | 
            -
                        <Button href=" | 
| 85 | 
            +
                        <Button href={docUrl("installation.html")}>Getting Started</Button>
         | 
| 86 86 | 
             
                      </PromoSection>
         | 
| 87 87 | 
             
                    </div>
         | 
| 88 88 | 
             
                  </SplashContainer>
         | 
    
        data/docs/web/sidebars.json
    CHANGED
    
    | @@ -3,29 +3,35 @@ | |
| 3 3 | 
             
                "Getting Started": [
         | 
| 4 4 | 
             
                  "installation",
         | 
| 5 5 | 
             
                  "basic_example",
         | 
| 6 | 
            -
                  " | 
| 6 | 
            +
                  "overview",
         | 
| 7 7 | 
             
                  "alternatives"
         | 
| 8 8 | 
             
                ],
         | 
| 9 9 | 
             
                "API": [
         | 
| 10 | 
            +
                  "operation",
         | 
| 10 11 | 
             
                  "include_association",
         | 
| 11 12 | 
             
                  "exclude_association",
         | 
| 12 13 | 
             
                  "nullify",
         | 
| 13 14 | 
             
                  "finalize",
         | 
| 15 | 
            +
                  "after_persist",
         | 
| 14 16 | 
             
                  "init_as",
         | 
| 15 17 | 
             
                  "traits",
         | 
| 16 | 
            -
                  "parameters" | 
| 17 | 
            -
                  "execution_order"
         | 
| 18 | 
            +
                  "parameters"
         | 
| 18 19 | 
             
                ],
         | 
| 19 20 | 
             
                "Adapters": [
         | 
| 20 21 | 
             
                  "supported_adapters",
         | 
| 21 22 | 
             
                  "active_record",
         | 
| 22 23 | 
             
                  "sequel"
         | 
| 23 24 | 
             
                ],
         | 
| 24 | 
            -
                " | 
| 25 | 
            +
                "Advanced Options": [
         | 
| 25 26 | 
             
                  "implicit_cloner",
         | 
| 26 27 | 
             
                  "inline_configuration",
         | 
| 28 | 
            +
                  "clone_mapper",
         | 
| 27 29 | 
             
                  "architecture",
         | 
| 30 | 
            +
                  "testing",
         | 
| 28 31 | 
             
                  "customization"
         | 
| 32 | 
            +
                ],
         | 
| 33 | 
            +
                "Upgrade Notes": [
         | 
| 34 | 
            +
                  "from_v02_to_v10"
         | 
| 29 35 | 
             
                ]
         | 
| 30 36 | 
             
              }
         | 
| 31 37 | 
             
            }
         | 
    
        data/docs/web/siteConfig.js
    CHANGED
    
    | @@ -8,8 +8,9 @@ | |
| 8 8 | 
             
            const siteConfig = {
         | 
| 9 9 | 
             
              title: 'Clowne' /* title for your website */,
         | 
| 10 10 | 
             
              tagline: 'A flexible gem for cloning your models',
         | 
| 11 | 
            -
              url: ' | 
| 12 | 
            -
               | 
| 11 | 
            +
              url: 'http://clowne.evilmartians.io' /* your website url */,
         | 
| 12 | 
            +
              cname: 'clowne.evilmartians.io',
         | 
| 13 | 
            +
              baseUrl: '/' /* base url for your project */,
         | 
| 13 14 | 
             
              customDocsPath: '../docs',
         | 
| 14 15 | 
             
              projectName: 'clowne',
         | 
| 15 16 | 
             
              headerLinks: [
         | 
| @@ -22,7 +23,7 @@ const siteConfig = { | |
| 22 23 | 
             
              favicon: 'img/favicon/favicon.ico',
         | 
| 23 24 | 
             
              /* colors for website */
         | 
| 24 25 | 
             
              colors: {
         | 
| 25 | 
            -
                primaryColor: '# | 
| 26 | 
            +
                primaryColor: '#9FA628', // '#ff5e5e'
         | 
| 26 27 | 
             
                secondaryColor: '#e3e3e3',
         | 
| 27 28 | 
             
              },
         | 
| 28 29 | 
             
              // This copyright info is used in /core/Footer.js and blog rss/atom feeds.
         | 
| @@ -33,12 +34,13 @@ const siteConfig = { | |
| 33 34 | 
             
              // organizationName: 'deltice', // or set an env variable ORGANIZATION_NAME
         | 
| 34 35 | 
             
              highlight: {
         | 
| 35 36 | 
             
                // Highlight.js theme to use for syntax highlighting in code blocks
         | 
| 36 | 
            -
                theme: ' | 
| 37 | 
            +
                theme: 'atom-one-light',
         | 
| 37 38 | 
             
              },
         | 
| 38 39 | 
             
              scripts: ['https://buttons.github.io/buttons.js'],
         | 
| 39 40 | 
             
              // You may provide arbitrary config keys to be used as needed by your template.
         | 
| 40 41 | 
             
              repoUrl: 'https://github.com/palkan/clowne',
         | 
| 41 42 | 
             
              gemUrl: 'https://rubygems.org/gems/clowne',
         | 
| 43 | 
            +
              gaTrackingId: 'UA-104346673-2',
         | 
| 42 44 | 
             
            };
         | 
| 43 45 |  | 
| 44 46 | 
             
            module.exports = siteConfig;
         | 
| @@ -4,13 +4,13 @@ | |
| 4 4 | 
             
              font-weight: 400;
         | 
| 5 5 | 
             
              font-style: normal;
         | 
| 6 6 | 
             
              font-family: "Stem Text";
         | 
| 7 | 
            -
              src: url(" | 
| 7 | 
            +
              src: url("//cdn.evilmartians.com/front/fonts/subset-StemText-Regular.woff") format("woff");
         | 
| 8 8 | 
             
            }
         | 
| 9 9 | 
             
            @font-face {
         | 
| 10 10 | 
             
              font-weight: 700;
         | 
| 11 11 | 
             
              font-style: normal;
         | 
| 12 12 | 
             
              font-family: "Stem Text";
         | 
| 13 | 
            -
              src: url(" | 
| 13 | 
            +
              src: url("//cdn.evilmartians.com/front/fonts/subset-StemText-Bold.woff") format("woff");
         | 
| 14 14 | 
             
            }
         | 
| 15 15 |  | 
| 16 16 | 
             
            @font-face {
         | 
| @@ -49,16 +49,15 @@ footer .sitemap div { | |
| 49 49 | 
             
            }
         | 
| 50 50 |  | 
| 51 51 | 
             
            .fixedHeaderContainer a {
         | 
| 52 | 
            -
              color: # | 
| 52 | 
            +
              color: #9FA628;
         | 
| 53 53 | 
             
            }
         | 
| 54 54 |  | 
| 55 55 | 
             
            header h2 {
         | 
| 56 | 
            -
              color: # | 
| 56 | 
            +
              color: #9FA628;
         | 
| 57 57 | 
             
              text-transform: uppercase;
         | 
| 58 58 | 
             
            }
         | 
| 59 59 |  | 
| 60 60 | 
             
            .container .wrapper h2 {
         | 
| 61 | 
            -
              color: #111; /* #ff5e5e; */
         | 
| 62 61 | 
             
              font-weight: bold;
         | 
| 63 62 | 
             
            }
         | 
| 64 63 |  | 
| @@ -66,6 +65,14 @@ header h2 { | |
| 66 65 | 
             
              text-decoration: underline;
         | 
| 67 66 | 
             
            }
         | 
| 68 67 |  | 
| 68 | 
            +
            .projectTitle {
         | 
| 69 | 
            +
              color: #111;
         | 
| 70 | 
            +
            }
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            .projectTitleName {
         | 
| 73 | 
            +
              color: #9FA628;
         | 
| 74 | 
            +
            }
         | 
| 75 | 
            +
             | 
| 69 76 | 
             
            .mainContainer .wrapper a:hover {
         | 
| 70 77 | 
             
              text-decoration: none;
         | 
| 71 78 | 
             
            }
         | 
| @@ -79,7 +86,7 @@ small { | |
| 79 86 | 
             
            }
         | 
| 80 87 |  | 
| 81 88 | 
             
            .navigationSlider .slidingNav ul li a {
         | 
| 82 | 
            -
              color: # | 
| 89 | 
            +
              color: #9FA628;
         | 
| 83 90 | 
             
            }
         | 
| 84 91 |  | 
| 85 92 | 
             
            nav.toc .toggleNav .navGroup.navGroupActive {
         | 
| @@ -91,9 +98,8 @@ nav.toc .toggleNav .navGroup.navGroupActive { | |
| 91 98 | 
             
              margin-bottom: 30px;
         | 
| 92 99 | 
             
            }
         | 
| 93 100 |  | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
              color: #a7a7a7;
         | 
| 101 | 
            +
            .hljs-doctag {
         | 
| 102 | 
            +
              color: #a0a1a7;
         | 
| 97 103 | 
             
            }
         | 
| 98 104 |  | 
| 99 105 | 
             
            @keyframes humanoids-blink{
         | 
| @@ -226,4 +232,4 @@ footer h5{ | |
| 226 232 | 
             
            .mainContainer {
         | 
| 227 233 | 
             
              background: none;
         | 
| 228 234 | 
             
              border-top: 1px solid #e3e3e3;
         | 
| 229 | 
            -
            }
         | 
| 235 | 
            +
            }
         | 
    
        data/gemfiles/jruby.gemfile
    CHANGED
    
    
    
        data/lib/clowne.rb
    CHANGED
    
    | @@ -9,11 +9,13 @@ require 'clowne/adapters/base' | |
| 9 9 | 
             
            # Declarative models cloning
         | 
| 10 10 | 
             
            module Clowne
         | 
| 11 11 | 
             
              # List of built-in adapters
         | 
| 12 | 
            +
              # rubocop:disable AlignHash
         | 
| 12 13 | 
             
              ADAPTERS = {
         | 
| 13 14 | 
             
                base:          'Base',
         | 
| 14 15 | 
             
                active_record: 'ActiveRecord',
         | 
| 15 16 | 
             
                sequel:        'Sequel'
         | 
| 16 17 | 
             
              }.freeze
         | 
| 18 | 
            +
              # rubocop:enable AlignHash
         | 
| 17 19 |  | 
| 18 20 | 
             
              class << self
         | 
| 19 21 | 
             
                attr_reader :default_adapter, :raise_on_override
         | 
| @@ -29,6 +31,7 @@ module Clowne | |
| 29 31 | 
             
                  elsif adapter.is_a?(Symbol)
         | 
| 30 32 | 
             
                    adapter_class = ADAPTERS[adapter]
         | 
| 31 33 | 
             
                    raise "Unknown adapter: #{adapter}" if adapter_class.nil?
         | 
| 34 | 
            +
             | 
| 32 35 | 
             
                    Clowne::Adapters.const_get(adapter_class).new
         | 
| 33 36 | 
             
                  else
         | 
| 34 37 | 
             
                    adapter
         | 
| @@ -5,8 +5,7 @@ require 'clowne/ext/orm_ext' | |
| 5 5 | 
             
            module Clowne
         | 
| 6 6 | 
             
              module Adapters
         | 
| 7 7 | 
             
                # Cloning adapter for ActiveRecord
         | 
| 8 | 
            -
                class ActiveRecord < Base
         | 
| 9 | 
            -
                end
         | 
| 8 | 
            +
                class ActiveRecord < Base; end
         | 
| 10 9 | 
             
              end
         | 
| 11 10 | 
             
            end
         | 
| 12 11 |  | 
| @@ -15,4 +14,4 @@ ActiveSupport.on_load(:active_record) do | |
| 15 14 | 
             
            end
         | 
| 16 15 |  | 
| 17 16 | 
             
            require 'clowne/adapters/active_record/associations'
         | 
| 18 | 
            -
            require 'clowne/adapters/active_record/association'
         | 
| 17 | 
            +
            require 'clowne/adapters/active_record/resolvers/association'
         | 
| @@ -9,7 +9,8 @@ module Clowne | |
| 9 9 | 
             
                      def call(record)
         | 
| 10 10 | 
             
                        child = association
         | 
| 11 11 | 
             
                        return record unless child
         | 
| 12 | 
            -
             | 
| 12 | 
            +
             | 
| 13 | 
            +
                        unless declaration.scope.nil?
         | 
| 13 14 | 
             
                          warn(
         | 
| 14 15 | 
             
                            '[Clowne] Has one association does not support scopes ' \
         | 
| 15 16 | 
             
                            "(#{@association_name} for #{@source.class})"
         | 
| @@ -0,0 +1,38 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Clowne
         | 
| 4 | 
            +
              module Adapters # :nodoc: all
         | 
| 5 | 
            +
                class ActiveRecord
         | 
| 6 | 
            +
                  module Resolvers
         | 
| 7 | 
            +
                    class UnknownAssociation < StandardError; end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    class Association
         | 
| 10 | 
            +
                      class << self
         | 
| 11 | 
            +
                        # rubocop: disable Metrics/ParameterLists
         | 
| 12 | 
            +
                        def call(source, record, declaration, adapter:, params:, **_options)
         | 
| 13 | 
            +
                          reflection = source.class.reflections[declaration.name.to_s]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                          if reflection.nil?
         | 
| 16 | 
            +
                            raise UnknownAssociation,
         | 
| 17 | 
            +
                                  "Association #{declaration.name} couldn't be found for #{source.class}"
         | 
| 18 | 
            +
                          end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                          cloner_class = Associations.cloner_for(reflection)
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                          cloner_class.new(reflection, source, declaration, adapter, params).call(record)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                          record
         | 
| 25 | 
            +
                        end
         | 
| 26 | 
            +
                        # rubocop: enable Metrics/ParameterLists
         | 
| 27 | 
            +
                      end
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            Clowne::Adapters::ActiveRecord.register_resolver(
         | 
| 35 | 
            +
              :association,
         | 
| 36 | 
            +
              Clowne::Adapters::ActiveRecord::Resolvers::Association,
         | 
| 37 | 
            +
              before: :nullify
         | 
| 38 | 
            +
            )
         | 
    
        data/lib/clowne/adapters/base.rb
    CHANGED
    
    | @@ -2,46 +2,34 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require 'clowne/adapters/registry'
         | 
| 4 4 |  | 
| 5 | 
            +
            require 'clowne/resolvers/init_as'
         | 
| 6 | 
            +
            require 'clowne/resolvers/nullify'
         | 
| 7 | 
            +
            require 'clowne/resolvers/finalize'
         | 
| 8 | 
            +
            require 'clowne/resolvers/after_persist'
         | 
| 9 | 
            +
             | 
| 5 10 | 
             
            module Clowne
         | 
| 6 11 | 
             
              module Adapters
         | 
| 7 12 | 
             
                # ORM-independant adapter (just calls #dup).
         | 
| 8 13 | 
             
                # Works with nullify/finalize.
         | 
| 9 14 | 
             
                class Base
         | 
| 10 | 
            -
                   | 
| 11 | 
            -
                    attr_reader :registry
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                    def inherited(subclass)
         | 
| 14 | 
            -
                      # Duplicate registry
         | 
| 15 | 
            -
                      subclass.registry = registry.dup
         | 
| 16 | 
            -
                    end
         | 
| 17 | 
            -
             | 
| 18 | 
            -
                    def resolver_for(type)
         | 
| 19 | 
            -
                      registry.mapping[type] || raise("Uknown resolver #{type} for #{self}")
         | 
| 20 | 
            -
                    end
         | 
| 15 | 
            +
                  include Clowne::Adapters::Registry::Container
         | 
| 21 16 |  | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
                       | 
| 28 | 
            -
                         | 
| 29 | 
            -
             | 
| 30 | 
            -
                        registry.insert_before before, type
         | 
| 31 | 
            -
                      else
         | 
| 32 | 
            -
                        registry.append type
         | 
| 17 | 
            +
                  class << self
         | 
| 18 | 
            +
                    # Duplicate record and remember record <-> clone relationship in operation
         | 
| 19 | 
            +
                    # Cab be overrided in special adapter
         | 
| 20 | 
            +
                    # +record+:: Instance of record (ActiveRecord or Sequel)
         | 
| 21 | 
            +
                    def dup_record(record)
         | 
| 22 | 
            +
                      record.dup.tap do |clone|
         | 
| 23 | 
            +
                        operation = operation_class.current
         | 
| 24 | 
            +
                        operation.add_mapping(record, clone)
         | 
| 33 25 | 
             
                      end
         | 
| 34 26 | 
             
                    end
         | 
| 35 27 |  | 
| 36 | 
            -
                     | 
| 37 | 
            -
             | 
| 38 | 
            -
                     | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
                  self.registry = Registry.new
         | 
| 42 | 
            -
             | 
| 43 | 
            -
                  def registry
         | 
| 44 | 
            -
                    self.class.registry
         | 
| 28 | 
            +
                    # Operation class which  using for cloning
         | 
| 29 | 
            +
                    # Cab be overrided in special adapter
         | 
| 30 | 
            +
                    def operation_class
         | 
| 31 | 
            +
                      Clowne::Utils::Operation
         | 
| 32 | 
            +
                    end
         | 
| 45 33 | 
             
                  end
         | 
| 46 34 |  | 
| 47 35 | 
             
                  # Using a plan make full duplicate of record
         | 
| @@ -50,19 +38,13 @@ module Clowne | |
| 50 38 | 
             
                  # +params+:: Custom params hash
         | 
| 51 39 | 
             
                  def clone(source, plan, params: {})
         | 
| 52 40 | 
             
                    declarations = plan.declarations
         | 
| 53 | 
            -
                     | 
| 41 | 
            +
                    init_record = init_record(self.class.dup_record(source))
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                    declarations.inject(init_record) do |record, (type, declaration)|
         | 
| 54 44 | 
             
                      resolver_for(type).call(source, record, declaration, params: params, adapter: self)
         | 
| 55 45 | 
             
                    end
         | 
| 56 46 | 
             
                  end
         | 
| 57 47 |  | 
| 58 | 
            -
                  def resolver_for(type)
         | 
| 59 | 
            -
                    self.class.resolver_for(type)
         | 
| 60 | 
            -
                  end
         | 
| 61 | 
            -
             | 
| 62 | 
            -
                  def dup_source(source)
         | 
| 63 | 
            -
                    source.dup
         | 
| 64 | 
            -
                  end
         | 
| 65 | 
            -
             | 
| 66 48 | 
             
                  def init_record(record)
         | 
| 67 49 | 
             
                    # Override in custom adapters
         | 
| 68 50 | 
             
                    record
         | 
| @@ -71,6 +53,23 @@ module Clowne | |
| 71 53 | 
             
              end
         | 
| 72 54 | 
             
            end
         | 
| 73 55 |  | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 56 | 
            +
            Clowne::Adapters::Base.register_resolver(
         | 
| 57 | 
            +
              :init_as,
         | 
| 58 | 
            +
              Clowne::Resolvers::InitAs,
         | 
| 59 | 
            +
              prepend: true
         | 
| 60 | 
            +
            )
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            Clowne::Adapters::Base.register_resolver(
         | 
| 63 | 
            +
              :nullify,
         | 
| 64 | 
            +
              Clowne::Resolvers::Nullify
         | 
| 65 | 
            +
            )
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            Clowne::Adapters::Base.register_resolver(
         | 
| 68 | 
            +
              :finalize, Clowne::Resolvers::Finalize,
         | 
| 69 | 
            +
              after: :nullify
         | 
| 70 | 
            +
            )
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            Clowne::Adapters::Base.register_resolver(
         | 
| 73 | 
            +
              :after_persist, Clowne::Resolvers::AfterPersist,
         | 
| 74 | 
            +
              after: :finalize
         | 
| 75 | 
            +
            )
         | 
| @@ -9,16 +9,15 @@ module Clowne | |
| 9 9 | 
             
                    # +source+:: Instance of cloned object (ex: User.new(posts: posts))
         | 
| 10 10 | 
             
                    # +declaration+:: = Relation description
         | 
| 11 11 | 
             
                    #                   (ex: Clowne::Declarations::IncludeAssociation.new(:posts))
         | 
| 12 | 
            +
                    # +adapter+:: Clowne adapter
         | 
| 12 13 | 
             
                    # +params+:: = Instance of Hash
         | 
| 13 | 
            -
                    def initialize(reflection, source, declaration, params)
         | 
| 14 | 
            +
                    def initialize(reflection, source, declaration, adapter, params)
         | 
| 14 15 | 
             
                      @source = source
         | 
| 15 | 
            -
                      @ | 
| 16 | 
            -
                      @ | 
| 16 | 
            +
                      @declaration = declaration
         | 
| 17 | 
            +
                      @adapter = adapter
         | 
| 17 18 | 
             
                      @params = params
         | 
| 18 19 | 
             
                      @association_name = declaration.name.to_s
         | 
| 19 20 | 
             
                      @reflection = reflection
         | 
| 20 | 
            -
                      @cloner_options = declaration.params_proxy.permit(params: params, parent: source)
         | 
| 21 | 
            -
                      @cloner_options.merge!(traits: declaration.traits) if declaration.traits
         | 
| 22 21 | 
             
                    end
         | 
| 23 22 |  | 
| 24 23 | 
             
                    def call(_record)
         | 
| @@ -31,24 +30,24 @@ module Clowne | |
| 31 30 |  | 
| 32 31 | 
             
                    def clone_one(child)
         | 
| 33 32 | 
             
                      cloner = cloner_for(child)
         | 
| 34 | 
            -
                      cloner ? cloner.call(child, cloner_options) :  | 
| 33 | 
            +
                      cloner ? cloner.call(child, cloner_options) : dup_record(child)
         | 
| 35 34 | 
             
                    end
         | 
| 36 35 |  | 
| 37 36 | 
             
                    def with_scope
         | 
| 38 | 
            -
                       | 
| 37 | 
            +
                      scope = declaration.scope
         | 
| 39 38 | 
             
                      if scope.is_a?(Symbol)
         | 
| 40 | 
            -
                         | 
| 39 | 
            +
                        init_scope.__send__(scope)
         | 
| 41 40 | 
             
                      elsif scope.is_a?(Proc)
         | 
| 42 | 
            -
                         | 
| 41 | 
            +
                        init_scope.instance_exec(params, &scope) || init_scope
         | 
| 43 42 | 
             
                      else
         | 
| 44 | 
            -
                         | 
| 43 | 
            +
                        init_scope
         | 
| 45 44 | 
             
                      end.to_a
         | 
| 46 45 | 
             
                    end
         | 
| 47 46 |  | 
| 48 47 | 
             
                    private
         | 
| 49 48 |  | 
| 50 | 
            -
                    def  | 
| 51 | 
            -
                       | 
| 49 | 
            +
                    def dup_record(record)
         | 
| 50 | 
            +
                      adapter.class.dup_record(record)
         | 
| 52 51 | 
             
                    end
         | 
| 53 52 |  | 
| 54 53 | 
             
                    def init_scope
         | 
| @@ -56,13 +55,23 @@ module Clowne | |
| 56 55 | 
             
                    end
         | 
| 57 56 |  | 
| 58 57 | 
             
                    def cloner_for(child)
         | 
| 59 | 
            -
                      return clone_with if clone_with
         | 
| 58 | 
            +
                      return declaration.clone_with if declaration.clone_with
         | 
| 60 59 |  | 
| 61 60 | 
             
                      return child.class.cloner_class if child.class.respond_to?(:cloner_class)
         | 
| 62 61 | 
             
                    end
         | 
| 63 62 |  | 
| 64 | 
            -
                     | 
| 65 | 
            -
             | 
| 63 | 
            +
                    def cloner_options
         | 
| 64 | 
            +
                      return @_cloner_options if defined?(@_cloner_options)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                      @_cloner_options = declaration.params_proxy.permit(
         | 
| 67 | 
            +
                        params: params, parent: source
         | 
| 68 | 
            +
                      ).tap do |options|
         | 
| 69 | 
            +
                        options[:adapter] = adapter
         | 
| 70 | 
            +
                        options.merge!(traits: declaration.traits) if declaration.traits
         | 
| 71 | 
            +
                      end
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                    attr_reader :source, :declaration, :adapter, :params, :association_name, :reflection
         | 
| 66 75 | 
             
                  end
         | 
| 67 76 | 
             
                end
         | 
| 68 77 | 
             
              end
         |