evil-seed 0.5.0 → 0.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: beab28e2e707c60ae58a1a30d000975f7b460918f369c7177800f732f34cfee5
4
- data.tar.gz: 710c2d0a680da6d0c558d50e448048ec5338693e6ce112745ac41a750d34cd3b
3
+ metadata.gz: dfdedee7cac6da3803d6071ccbda5eaf19ee07bc07c67775b202160c304dd323
4
+ data.tar.gz: e04bc0672ccb683928651843c749ad05378af846c6d4b51d7e7c3d14eb43c179
5
5
  SHA512:
6
- metadata.gz: 0de18595e7b4498352c7056f6b9f3c1baf5fe4263cc64f202a1cc06642077767bbe8950c94553cc70fc3157f90687807e851cf6b99403f8a367329045a97bea2
7
- data.tar.gz: df586316b366d0b4657cf25cdf6ac56610296c6faa630d1dfdc7314f605df7c2f9454c3f7af72a5f9dea1fd7987bdf553fbd5cf44dff7fd6657dd514a7c15206
6
+ metadata.gz: d2973540b6fd16936419e9e76e389df4dd854313e3674ff7c73f7056c18c3e8979ca302d0c395a60e3a17abb7f9bc2b886ef4939711ad43c3df72cebc06cf944
7
+ data.tar.gz: cb2772174b471dc7977fcaa00bc79dc0bf45429f836a7e490487d37e625f4d8328583d1d103b13d2a8899e56736793acb24e35fd362c196aab1a60489f023159
@@ -0,0 +1,86 @@
1
+ name: Release gem
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - v*
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+ id-token: write
14
+ packages: write
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+ with:
18
+ fetch-depth: 0 # Fetch current tag as annotated. See https://github.com/actions/checkout/issues/290
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: "3.3"
22
+ - name: "Extract data from tag: version, message, body"
23
+ id: tag
24
+ run: |
25
+ git fetch --tags --force # Really fetch annotated tag. See https://github.com/actions/checkout/issues/290#issuecomment-680260080
26
+ echo ::set-output name=version::${GITHUB_REF#refs/tags/v}
27
+ echo ::set-output name=subject::$(git for-each-ref $GITHUB_REF --format='%(contents:subject)')
28
+ BODY="$(git for-each-ref $GITHUB_REF --format='%(contents:body)')"
29
+ # Extract changelog entries between this and previous version headers
30
+ escaped_version=$(echo ${GITHUB_REF#refs/tags/v} | sed -e 's/[]\/$*.^[]/\\&/g')
31
+ changelog=$(awk "BEGIN{inrelease=0} /## \[${escaped_version}\]/{inrelease=1;next} /## \[[0-9]+\.[0-9]+\.[0-9]+.*?\]/{inrelease=0;exit} {if (inrelease) print}" CHANGELOG.md)
32
+ # Multiline body for release. See https://github.community/t/set-output-truncates-multiline-strings/16852/5
33
+ BODY="${BODY}"$'\n'"${changelog}"
34
+ BODY="${BODY//'%'/'%25'}"
35
+ BODY="${BODY//$'\n'/'%0A'}"
36
+ BODY="${BODY//$'\r'/'%0D'}"
37
+ echo "::set-output name=body::$BODY"
38
+ # Add pre-release option if tag name has any suffix after vMAJOR.MINOR.PATCH
39
+ if [[ ${GITHUB_REF#refs/tags/} =~ ^v[0-9]+\.[0-9]+\.[0-9]+.+ ]]; then
40
+ echo ::set-output name=prerelease::true
41
+ fi
42
+ - name: Build gem
43
+ run: gem build
44
+ - name: Calculate checksums
45
+ run: sha256sum evil-seed-${{ steps.tag.outputs.version }}.gem > SHA256SUM
46
+ - name: Check version
47
+ run: ls -l evil-seed-${{ steps.tag.outputs.version }}.gem
48
+ - name: Create Release
49
+ id: create_release
50
+ uses: actions/create-release@v1
51
+ env:
52
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
53
+ with:
54
+ tag_name: ${{ github.ref }}
55
+ release_name: ${{ steps.tag.outputs.subject }}
56
+ body: ${{ steps.tag.outputs.body }}
57
+ draft: false
58
+ prerelease: ${{ steps.tag.outputs.prerelease }}
59
+ - name: Upload built gem as release asset
60
+ uses: actions/upload-release-asset@v1
61
+ env:
62
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
63
+ with:
64
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
65
+ asset_path: evil-seed-${{ steps.tag.outputs.version }}.gem
66
+ asset_name: evil-seed-${{ steps.tag.outputs.version }}.gem
67
+ asset_content_type: application/x-tar
68
+ - name: Upload checksums as release asset
69
+ uses: actions/upload-release-asset@v1
70
+ env:
71
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
72
+ with:
73
+ upload_url: ${{ steps.create_release.outputs.upload_url }}
74
+ asset_path: SHA256SUM
75
+ asset_name: SHA256SUM
76
+ asset_content_type: text/plain
77
+ - name: Publish to GitHub packages
78
+ env:
79
+ GEM_HOST_API_KEY: Bearer ${{ secrets.GITHUB_TOKEN }}
80
+ run: |
81
+ gem push evil-seed-${{ steps.tag.outputs.version }}.gem --host https://rubygems.pkg.github.com/${{ github.repository_owner }}
82
+ - name: Configure RubyGems Credentials
83
+ uses: rubygems/configure-rubygems-credentials@main
84
+ - name: Publish to RubyGems
85
+ run: |
86
+ gem push evil-seed-${{ steps.tag.outputs.version }}.gem
@@ -19,12 +19,15 @@ jobs:
19
19
  - ruby: "head"
20
20
  activerecord: "head"
21
21
  database: sqlite
22
- - ruby: "3.2"
23
- activerecord: "7.0"
22
+ - ruby: "3.3"
23
+ activerecord: "7.1"
24
24
  database: postgresql
25
- - ruby: "3.2"
26
- activerecord: "7.0"
25
+ - ruby: "3.3"
26
+ activerecord: "7.1"
27
27
  database: mysql
28
+ - ruby: "3.3"
29
+ activerecord: "7.1"
30
+ database: sqlite
28
31
  - ruby: "3.2"
29
32
  activerecord: "7.0"
30
33
  database: sqlite
@@ -34,15 +37,12 @@ jobs:
34
37
  - ruby: "3.0"
35
38
  activerecord: "6.0"
36
39
  database: sqlite
37
- - ruby: "2.7"
38
- activerecord: "5.2"
39
- database: sqlite
40
40
 
41
41
  runs-on: ubuntu-latest
42
42
 
43
43
  services:
44
44
  postgres:
45
- image: postgres:15
45
+ image: postgres:16
46
46
  env:
47
47
  POSTGRES_USER: postgres
48
48
  POSTGRES_PASSWORD: postgres
@@ -54,7 +54,7 @@ jobs:
54
54
  --health-timeout 5s
55
55
  --health-retries 5
56
56
  mysql:
57
- image: mysql:8.0
57
+ image: mysql:8.4
58
58
  env:
59
59
  MYSQL_ALLOW_EMPTY_PASSWORD: yes
60
60
  MYSQL_DATABASE: evil_seed_test
@@ -70,7 +70,7 @@ jobs:
70
70
  POSTGRES_PASSWORD: postgres
71
71
 
72
72
  steps:
73
- - uses: actions/checkout@v3
73
+ - uses: actions/checkout@v4
74
74
  - uses: ruby/setup-ruby@v1
75
75
  with:
76
76
  ruby-version: ${{ matrix.ruby }}
data/CHANGELOG.md ADDED
@@ -0,0 +1,74 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.6.0] - 2024-06-18
11
+
12
+ ### Added
13
+
14
+ - Association inclusion option. [@gazay] ([#13](https://github.com/evilmartians/evil-seed/pull/13))
15
+ - Option to limit association depth. [@gazay] ([#13](https://github.com/evilmartians/evil-seed/pull/13))
16
+ - Option to ignore `default_scope` in models. [@gazay] ([#13](https://github.com/evilmartians/evil-seed/pull/13))
17
+ - Option to disable nullifying of foreign keys. [@gazay] ([#13](https://github.com/evilmartians/evil-seed/pull/13))
18
+
19
+ ## [0.5.0] - 2023-02-16
20
+
21
+ ### Added
22
+
23
+ - Option to ignore columns from a given model. [@nhocki] ([#17](https://github.com/evilmartians/evil-seed/pull/17))
24
+
25
+ ## [0.4.0] - 2022-12-07
26
+
27
+ ### Fixed
28
+
29
+ - Ignore generated database columns. [@cmer] ([#16](https://github.com/evilmartians/evil-seed/pull/16))
30
+
31
+ ## [0.3.0] - 2022-03-14
32
+
33
+ ### Added
34
+
35
+ - Passing attribute value to anonymizer block (to partially modify it). [@Envek]
36
+
37
+ ## [0.2.0] - 2022-03-10
38
+
39
+ ### Fixed
40
+
41
+ - Ignore virtual ActiveRecord attributes. [@Envek]
42
+
43
+ ### Removed
44
+
45
+ - Support for ActiveRecord 4.2
46
+
47
+ ## [0.1.3] - 2021-09-02
48
+
49
+ ### Fixed
50
+
51
+ - Compatibility with Ruby 3.0 and ActiveRecord 6.x.
52
+
53
+ ## [0.1.2] - 2018-03-27
54
+
55
+ ### Fixed
56
+
57
+ - Bug with unwanted pseudo columns in dump when dumping HABTM join table without one side.
58
+
59
+ ## [0.1.1] - 2017-05-15
60
+
61
+ ### Fixed
62
+
63
+ - ActiveRecord 4.2 support by backporting of `ActiveRecord::Relation#in_batches`
64
+ - Dumping of the whole model without constraints
65
+
66
+ ## [0.1.0] - 2017-05-09
67
+
68
+ Initial release. [@palkan], [@Envek]
69
+
70
+ [@Envek]: https://github.com/Envek "Andrey Novikov"
71
+ [@palkan]: https://github.com/palkan "Vladimir Dementyev"
72
+ [@cmer]: https://github.com/cmer "Carl Mercier"
73
+ [@nhocki]: https://github.com/nhocki "Nicolás Hock-Isaza"
74
+ [@gazay]: https://github.com/gazay "Alex Gaziev"
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in evil-seed.gemspec
6
6
  gemspec
7
7
 
8
- activerecord_version = ENV.fetch("ACTIVERECORD_VERSION", "~> 7.0")
8
+ activerecord_version = ENV.fetch("ACTIVERECORD_VERSION", "~> 7.1")
9
9
  case activerecord_version.upcase
10
10
  when "HEAD"
11
11
  git "https://github.com/rails/rails.git" do
@@ -15,4 +15,5 @@ when "HEAD"
15
15
  else
16
16
  activerecord_version = "~> #{activerecord_version}.0" if activerecord_version.match?(/^\d+\.\d+$/)
17
17
  gem "activerecord", activerecord_version
18
+ gem "sqlite3", "~> 1.4"
18
19
  end
data/README.md CHANGED
@@ -52,7 +52,10 @@ EvilSeed.configure do |config|
52
52
  #
53
53
  # Association path is a dot-delimited string of association chain starting from model itself:
54
54
  # example: "forum.users.questions"
55
- root.exclude(/\btracking_pixels\b/, 'forum.popular_questions')
55
+ root.exclude(/\btracking_pixels\b/, 'forum.popular_questions', /\Aforum\.parent\b/)
56
+
57
+ # Include back only certain associations
58
+ root.include(/\Aforum(\.parent(\.questions(\.answers)?)?)?\z/)
56
59
 
57
60
  # It's possible to limit the number of included into dump has_many and has_one records for every association
58
61
  # Note that belongs_to records for all not excluded associations are always dumped to keep referential integrity.
@@ -60,6 +63,11 @@ EvilSeed.configure do |config|
60
63
 
61
64
  # Or for certain association only
62
65
  root.limit_associations_size(10, 'forum.questions')
66
+
67
+ # Limit the depth of associations to be dumped from the root level
68
+ # All traverses through has_many, belongs_to, etc are counted
69
+ # So forum.subforums.subforums.questions.answers will be 5 levels deep
70
+ root.limit_deep(10)
63
71
  end
64
72
 
65
73
  # Everything you can pass to +where+ method will work as constraints:
@@ -95,6 +103,20 @@ EvilSeed.configure do |config|
95
103
  # This will remove the columns even if the model is not a root node and is
96
104
  # dumped via an association.
97
105
  config.ignore_columns("Profile", :name)
106
+
107
+ # Disable foreign key nullification for records that are not included in the dump
108
+ # By default, EvilSeed will nullify foreign keys for records that are not included in the dump
109
+ config.dont_nullify = true
110
+
111
+ # Unscope relations to include soft-deleted records etc
112
+ # This is useful when you want to include all records, including those that are hidden by default
113
+ # By default, EvilSeed will abide default scope of models
114
+ config.unscoped = true
115
+
116
+ # Verbose mode will print out the progress of the dump to the console along with writing the file
117
+ # By default, verbose mode is off
118
+ config.verbose = true
119
+ config.verbose_sql = true
98
120
  end
99
121
  ```
100
122
 
@@ -5,16 +5,19 @@ module EvilSeed
5
5
  # Configuration for dumping some root model and its associations
6
6
  class Root
7
7
  attr_reader :model, :constraints
8
- attr_reader :total_limit, :association_limits
9
- attr_reader :exclusions
8
+ attr_reader :total_limit, :association_limits, :deep_limit, :dont_nullify
9
+ attr_reader :exclusions, :inclusions
10
10
 
11
11
  # @param model [String] Name of the model class to dump
12
12
  # @param constraints [String, Hash] Everything you can feed into +where+ to limit number of records
13
- def initialize(model, *constraints)
13
+ def initialize(model, dont_nullify, *constraints)
14
14
  @model = model
15
15
  @constraints = constraints
16
16
  @exclusions = []
17
+ @inclusions = []
17
18
  @association_limits = {}
19
+ @deep_limit = nil
20
+ @dont_nullify = dont_nullify
18
21
  end
19
22
 
20
23
  # Exclude some of associations from the dump
@@ -23,6 +26,12 @@ module EvilSeed
23
26
  @exclusions += association_patterns
24
27
  end
25
28
 
29
+ # Include some excluded associations back to the dump
30
+ # @param association_patterns Array<String, Regex> Patterns to exclude associated models from dump
31
+ def include(*association_patterns)
32
+ @inclusions += association_patterns
33
+ end
34
+
26
35
  # Limit number of records in all (if pattern is not provided) or given associations to include into dump
27
36
  # @param limit [Integer] Maximum number of records in associations to include into dump
28
37
  # @param association_pattern [String, Regex] Pattern to limit number of records for certain associated models
@@ -34,8 +43,22 @@ module EvilSeed
34
43
  end
35
44
  end
36
45
 
46
+ # Limit deepenes of associations to include into dump
47
+ # @param limit [Integer] Maximum level to recursively dive into associations
48
+ def limit_deep(limit)
49
+ @deep_limit = limit
50
+ end
51
+
52
+ def do_not_nullify(nullify_flag)
53
+ @dont_nullify = nullify_flag
54
+ end
55
+
37
56
  def excluded?(association_path)
38
- exclusions.any? { |exclusion| exclusion.match(association_path) }
57
+ exclusions.any? { |exclusion| association_path.match(exclusion) } #.match(association_path) }
58
+ end
59
+
60
+ def included?(association_path)
61
+ inclusions.any? { |inclusion| association_path.match(inclusion) } #.match(association_path) }
39
62
  end
40
63
  end
41
64
  end
@@ -7,10 +7,14 @@ require_relative 'anonymizer'
7
7
  module EvilSeed
8
8
  # This module holds configuration for creating dump: which models and their constraints
9
9
  class Configuration
10
- attr_accessor :record_dumper_class
10
+ attr_accessor :record_dumper_class, :verbose, :verbose_sql, :unscoped, :dont_nullify
11
11
 
12
12
  def initialize
13
13
  @record_dumper_class = RecordDumper
14
+ @verbose = false
15
+ @verbose_sql = false
16
+ @unscoped = false
17
+ @dont_nullify = false
14
18
  @ignored_columns = Hash.new { |h, k| h[k] = [] }
15
19
  end
16
20
 
@@ -19,7 +23,7 @@ module EvilSeed
19
23
  end
20
24
 
21
25
  def root(model, *constraints)
22
- new_root = Root.new(model, *constraints)
26
+ new_root = Root.new(model, dont_nullify, *constraints)
23
27
  yield new_root if block_given?
24
28
  roots << new_root
25
29
  end
@@ -65,11 +65,17 @@ module EvilSeed
65
65
 
66
66
  def write!(attributes)
67
67
  # Remove non-insertable columns from attributes
68
- attributes = attributes.slice(*insertable_column_names)
68
+ attributes = prepare(attributes.slice(*insertable_column_names))
69
+
70
+ if configuration.verbose_sql
71
+ puts("-- #{relation_dumper.association_path}\n")
72
+ puts(@tuples_written.zero? ? insert_statement : ",\n")
73
+ puts(" (#{attributes.join(', ')})")
74
+ end
69
75
 
70
76
  @output.write("-- #{relation_dumper.association_path}\n") && @header_written = true unless @header_written
71
77
  @output.write(@tuples_written.zero? ? insert_statement : ",\n")
72
- @output.write(" (#{prepare(attributes).join(', ')})")
78
+ @output.write(" (#{attributes.join(', ')})")
73
79
  @tuples_written += 1
74
80
  @output.write(";\n") && @tuples_written = 0 if @tuples_written == MAX_TUPLES_PER_INSERT_STMT
75
81
  end
@@ -84,7 +90,7 @@ module EvilSeed
84
90
  attributes.map do |key, value|
85
91
  type = model_class.attribute_types[key]
86
92
  model_class.connection.quote(type.serialize(value))
87
- end
93
+ end.flatten.compact
88
94
  end
89
95
  end
90
96
  end
@@ -25,13 +25,15 @@ module EvilSeed
25
25
 
26
26
  attr_reader :relation, :root_dumper, :model_class, :association_path, :search_key, :identifiers, :nullify_columns,
27
27
  :belongs_to_reflections, :has_many_reflections, :foreign_keys, :loaded_ids, :to_load_map,
28
- :record_dumper, :inverse_reflection, :table_names, :options
28
+ :record_dumper, :inverse_reflection, :table_names, :options,
29
+ :current_deep, :verbose
29
30
 
30
- delegate :root, :configuration, :total_limit, :loaded_map, to: :root_dumper
31
+ delegate :root, :configuration, :dont_nullify, :total_limit, :deep_limit, :loaded_map, to: :root_dumper
31
32
 
32
33
  def initialize(relation, root_dumper, association_path, **options)
33
34
  @relation = relation
34
35
  @root_dumper = root_dumper
36
+ @verbose = configuration.verbose
35
37
  @identifiers = options[:identifiers]
36
38
  @to_load_map = Hash.new { |h, k| h[k] = [] }
37
39
  @foreign_keys = Hash.new { |h, k| h[k] = [] }
@@ -46,15 +48,23 @@ module EvilSeed
46
48
  @belongs_to_reflections = setup_belongs_to_reflections
47
49
  @has_many_reflections = setup_has_many_reflections
48
50
  @options = options
51
+ @current_deep = association_path.split('.').size
52
+ @dont_nullify = dont_nullify
53
+
54
+ puts("- #{association_path}") if verbose
49
55
  end
50
56
 
51
57
  # Generate dump and write it into +io+
52
58
  # @return [Array<IO>] List of dump IOs for separate tables in order of dependencies (belongs_to are first)
53
59
  def call
54
60
  dump!
55
- belongs_to_dumps = dump_belongs_to_associations!
56
- has_many_dumps = dump_has_many_associations!
57
- [belongs_to_dumps, record_dumper.result, has_many_dumps].flatten.compact
61
+ if deep_limit and current_deep > deep_limit
62
+ [record_dumper.result].flatten.compact
63
+ else
64
+ belongs_to_dumps = dump_belongs_to_associations!
65
+ has_many_dumps = dump_has_many_associations!
66
+ [belongs_to_dumps, record_dumper.result, has_many_dumps].flatten.compact
67
+ end
58
68
  end
59
69
 
60
70
  private
@@ -64,16 +74,22 @@ module EvilSeed
64
74
  model_class.ignored_columns += Array(configuration.ignored_columns_for(model_class.sti_name))
65
75
  model_class.send(:reload_schema_from_cache) if ActiveRecord.version < Gem::Version.new("6.1.0.rc1") # See https://github.com/rails/rails/pull/37581
66
76
  if identifiers.present?
77
+ puts(" # #{search_key} => #{identifiers}") if verbose
67
78
  # Don't use AR::Base#find_each as we will get error on Oracle if we will have more than 1000 ids in IN statement
68
79
  identifiers.in_groups_of(MAX_IDENTIFIERS_IN_IN_STMT).each do |ids|
69
- fetch_attributes(relation.where(search_key => ids.compact)).each do |attributes|
80
+ attrs = fetch_attributes(relation.where(search_key => ids.compact))
81
+ puts(" -- dumped #{attrs.size}") if verbose
82
+ attrs.each do |attributes|
70
83
  next unless check_limits!
71
84
  dump_record!(attributes)
72
85
  end
73
86
  end
74
87
  else
88
+ puts(" # #{relation.count}") if verbose
75
89
  relation.in_batches do |relation|
76
- fetch_attributes(relation).each do |attributes|
90
+ attrs = fetch_attributes(relation)
91
+ puts(" -- dumped #{attrs.size}") if verbose
92
+ attrs.each do |attributes|
77
93
  next unless check_limits!
78
94
  dump_record!(attributes)
79
95
  end
@@ -84,8 +100,10 @@ module EvilSeed
84
100
  end
85
101
 
86
102
  def dump_record!(attributes)
87
- nullify_columns.each do |nullify_column|
88
- attributes[nullify_column] = nil
103
+ unless dont_nullify
104
+ nullify_columns.each do |nullify_column|
105
+ attributes[nullify_column] = nil
106
+ end
89
107
  end
90
108
  return unless record_dumper.call(attributes)
91
109
  foreign_keys.each do |reflection_name, fk_column|
@@ -140,7 +158,11 @@ module EvilSeed
140
158
  end
141
159
 
142
160
  def build_relation(reflection)
143
- relation = reflection.klass.all
161
+ if configuration.unscoped
162
+ relation = reflection.klass.unscoped
163
+ else
164
+ relation = reflection.klass.all
165
+ end
144
166
  relation = relation.instance_eval(&reflection.scope) if reflection.scope
145
167
  relation = relation.where(reflection.type => model_class.to_s) if reflection.options[:as] # polymorphic
146
168
  relation
@@ -149,23 +171,32 @@ module EvilSeed
149
171
  def setup_belongs_to_reflections
150
172
  model_class.reflect_on_all_associations(:belongs_to).reject do |reflection|
151
173
  next false if reflection.options[:polymorphic] # TODO: Add support for polymorphic belongs_to
174
+ included = root.included?("#{association_path}.#{reflection.name}")
152
175
  excluded = root.excluded?("#{association_path}.#{reflection.name}") || reflection.name == inverse_reflection
153
- if excluded
154
- nullify_columns << reflection.foreign_key if model_class.column_names.include?(reflection.foreign_key)
176
+ if excluded and not included
177
+ if model_class.column_names.include?(reflection.foreign_key)
178
+ puts(" -- excluded #{reflection.foreign_key}") if verbose
179
+ nullify_columns << reflection.foreign_key
180
+ end
155
181
  else
156
182
  foreign_keys[reflection.name] = reflection.foreign_key
157
183
  table_names[reflection.name] = reflection.table_name
158
184
  end
159
- excluded
185
+ excluded and not included
160
186
  end
161
187
  end
162
188
 
163
189
  # This method returns only direct has_one and has_many reflections. For HABTM it returns intermediate has_many
164
190
  def setup_has_many_reflections
191
+ puts(" -- reflections #{model_class._reflections.keys}") if verbose
165
192
  model_class._reflections.select do |_reflection_name, reflection|
166
193
  next false if model_class.primary_key.nil?
194
+
167
195
  next false if reflection.is_a?(ActiveRecord::Reflection::ThroughReflection)
168
- %i[has_one has_many].include?(reflection.macro) && !root.excluded?("#{association_path}.#{reflection.name}")
196
+
197
+ included = root.included?("#{association_path}.#{reflection.name}")
198
+ excluded = root.excluded?("#{association_path}.#{reflection.name}") || reflection.name == inverse_reflection
199
+ %i[has_one has_many].include?(reflection.macro) && !(excluded and not included)
169
200
  end.map(&:second)
170
201
  end
171
202
  end
@@ -5,7 +5,7 @@ require_relative 'relation_dumper'
5
5
  module EvilSeed
6
6
  # This module collects dumps generation for root and all it's dependencies
7
7
  class RootDumper
8
- attr_reader :root, :dumper, :model_class, :total_limit, :association_limits
8
+ attr_reader :root, :dumper, :model_class, :total_limit, :deep_limit, :dont_nullify, :association_limits
9
9
 
10
10
  delegate :loaded_map, :configuration, to: :dumper
11
11
 
@@ -14,6 +14,8 @@ module EvilSeed
14
14
  @dumper = dumper
15
15
  @to_load_map = {}
16
16
  @total_limit = root.total_limit
17
+ @deep_limit = root.deep_limit
18
+ @dont_nullify = root.dont_nullify
17
19
  @association_limits = root.association_limits.dup
18
20
 
19
21
  @model_class = root.model.constantize
@@ -24,6 +26,7 @@ module EvilSeed
24
26
  def call
25
27
  association_path = model_class.model_name.singular
26
28
  relation = model_class.all
29
+ relation = relation.unscoped if configuration.unscoped
27
30
  relation = relation.where(*root.constraints) if root.constraints.any? # without arguments returns not a relation
28
31
  RelationDumper.new(relation, self, association_path).call
29
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module EvilSeed
4
- VERSION = '0.5.0'
4
+ VERSION = '0.6.0'
5
5
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evil-seed
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Novikov
8
8
  - Vladimir Dementyev
9
- autorequire:
9
+ autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-02-16 00:00:00.000000000 Z
12
+ date: 2024-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -146,9 +146,11 @@ executables: []
146
146
  extensions: []
147
147
  extra_rdoc_files: []
148
148
  files:
149
+ - ".github/workflows/release.yml"
149
150
  - ".github/workflows/test.yml"
150
151
  - ".gitignore"
151
152
  - ".rubocop.yml"
153
+ - CHANGELOG.md
152
154
  - Gemfile
153
155
  - LICENSE.txt
154
156
  - README.md
@@ -173,7 +175,7 @@ homepage: https://github.com/palkan/evil-seed
173
175
  licenses:
174
176
  - MIT
175
177
  metadata: {}
176
- post_install_message:
178
+ post_install_message:
177
179
  rdoc_options: []
178
180
  require_paths:
179
181
  - lib
@@ -188,8 +190,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
190
  - !ruby/object:Gem::Version
189
191
  version: '0'
190
192
  requirements: []
191
- rubygems_version: 3.3.7
192
- signing_key:
193
+ rubygems_version: 3.5.11
194
+ signing_key:
193
195
  specification_version: 4
194
196
  summary: Create partial and anonymized production database dumps for use in development
195
197
  test_files: []