dirty_seed 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +44 -0
  4. data/Rakefile +22 -0
  5. data/lib/dirty_seed.rb +23 -0
  6. data/lib/dirty_seed/assigners/dirty_assigner.rb +32 -0
  7. data/lib/dirty_seed/assigners/dirty_boolean.rb +14 -0
  8. data/lib/dirty_seed/assigners/dirty_date.rb +14 -0
  9. data/lib/dirty_seed/assigners/dirty_float.rb +28 -0
  10. data/lib/dirty_seed/assigners/dirty_integer.rb +86 -0
  11. data/lib/dirty_seed/assigners/dirty_string.rb +49 -0
  12. data/lib/dirty_seed/assigners/dirty_time.rb +14 -0
  13. data/lib/dirty_seed/data_model.rb +80 -0
  14. data/lib/dirty_seed/dirty_association.rb +106 -0
  15. data/lib/dirty_seed/dirty_attribute.rb +64 -0
  16. data/lib/dirty_seed/dirty_model.rb +123 -0
  17. data/lib/dirty_seed/engine.rb +11 -0
  18. data/lib/dirty_seed/exceptions.rb +6 -0
  19. data/lib/dirty_seed/method_missing_helper.rb +49 -0
  20. data/lib/dirty_seed/sorter.rb +118 -0
  21. data/lib/dirty_seed/version.rb +6 -0
  22. data/lib/tasks/dirty_seed_tasks.rake +8 -0
  23. data/spec/dummy/Rakefile +6 -0
  24. data/spec/dummy/app/assets/config/manifest.js +3 -0
  25. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  26. data/spec/dummy/app/channels/application_cable/channel.rb +4 -0
  27. data/spec/dummy/app/channels/application_cable/connection.rb +4 -0
  28. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  29. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  30. data/spec/dummy/app/javascript/packs/application.js +15 -0
  31. data/spec/dummy/app/jobs/application_job.rb +7 -0
  32. data/spec/dummy/app/mailers/application_mailer.rb +4 -0
  33. data/spec/dummy/app/models/alfa.rb +5 -0
  34. data/spec/dummy/app/models/application_record.rb +3 -0
  35. data/spec/dummy/app/models/bravo.rb +3 -0
  36. data/spec/dummy/app/models/charlie.rb +5 -0
  37. data/spec/dummy/app/models/delta.rb +4 -0
  38. data/spec/dummy/app/models/echo.rb +3 -0
  39. data/spec/dummy/app/models/foxtrot.rb +2 -0
  40. data/spec/dummy/app/models/golf.rb +2 -0
  41. data/spec/dummy/app/models/hotel.rb +4 -0
  42. data/spec/dummy/app/models/india.rb +4 -0
  43. data/spec/dummy/app/models/juliett.rb +21 -0
  44. data/spec/dummy/app/models/kilo.rb +2 -0
  45. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  46. data/spec/dummy/app/views/layouts/mailer.html.erb +13 -0
  47. data/spec/dummy/app/views/layouts/mailer.text.erb +1 -0
  48. data/spec/dummy/bin/rails +4 -0
  49. data/spec/dummy/bin/rake +4 -0
  50. data/spec/dummy/bin/setup +33 -0
  51. data/spec/dummy/config.ru +5 -0
  52. data/spec/dummy/config/application.rb +18 -0
  53. data/spec/dummy/config/boot.rb +5 -0
  54. data/spec/dummy/config/cable.yml +10 -0
  55. data/spec/dummy/config/database.yml +25 -0
  56. data/spec/dummy/config/environment.rb +5 -0
  57. data/spec/dummy/config/environments/development.rb +62 -0
  58. data/spec/dummy/config/environments/production.rb +112 -0
  59. data/spec/dummy/config/environments/test.rb +49 -0
  60. data/spec/dummy/config/initializers/application_controller_renderer.rb +8 -0
  61. data/spec/dummy/config/initializers/assets.rb +12 -0
  62. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  63. data/spec/dummy/config/initializers/content_security_policy.rb +28 -0
  64. data/spec/dummy/config/initializers/cookies_serializer.rb +5 -0
  65. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  66. data/spec/dummy/config/initializers/inflections.rb +27 -0
  67. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  68. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  69. data/spec/dummy/config/locales/en.yml +33 -0
  70. data/spec/dummy/config/puma.rb +38 -0
  71. data/spec/dummy/config/routes.rb +3 -0
  72. data/spec/dummy/config/spring.rb +6 -0
  73. data/spec/dummy/config/storage.yml +34 -0
  74. data/spec/dummy/db/development.sqlite3 +0 -0
  75. data/spec/dummy/db/migrate/20200923100317_create_alfas.rb +15 -0
  76. data/spec/dummy/db/migrate/20200923100328_create_bravos.rb +12 -0
  77. data/spec/dummy/db/migrate/20200923100329_create_charlies.rb +9 -0
  78. data/spec/dummy/db/migrate/20200923100330_create_deltas.rb +10 -0
  79. data/spec/dummy/db/migrate/20200923100331_create_echos.rb +9 -0
  80. data/spec/dummy/db/migrate/20200923100332_create_foxtrots.rb +9 -0
  81. data/spec/dummy/db/migrate/20200923100334_create_hotels.rb +7 -0
  82. data/spec/dummy/db/migrate/20200923100335_create_indias.rb +11 -0
  83. data/spec/dummy/db/migrate/20200923100336_create_julietts.rb +11 -0
  84. data/spec/dummy/db/migrate/20200923100337_create_kilos.rb +13 -0
  85. data/spec/dummy/db/schema.rb +105 -0
  86. data/spec/dummy/db/test.sqlite3 +0 -0
  87. data/spec/dummy/log/development.log +217 -0
  88. data/spec/dummy/log/test.log +95379 -0
  89. data/spec/dummy/public/404.html +67 -0
  90. data/spec/dummy/public/422.html +67 -0
  91. data/spec/dummy/public/500.html +66 -0
  92. data/spec/dummy/public/apple-touch-icon-precomposed.png +0 -0
  93. data/spec/dummy/public/apple-touch-icon.png +0 -0
  94. data/spec/dummy/public/favicon.ico +0 -0
  95. data/spec/dummy/spec/factories/bars.rb +8 -0
  96. data/spec/dummy/spec/factories/foos.rb +7 -0
  97. data/spec/dummy/spec/models/alfa_spec.rb +6 -0
  98. data/spec/dummy/spec/models/bravo_spec.rb +6 -0
  99. data/spec/dummy/spec/models/charlie_spec.rb +6 -0
  100. data/spec/dummy/spec/models/delta_spec.rb +6 -0
  101. data/spec/dummy/spec/models/echo_spec.rb +6 -0
  102. data/spec/dummy/tmp/development_secret.txt +1 -0
  103. data/spec/lib/dirty_seed/assigners/dirty_assigner_spec.rb +13 -0
  104. data/spec/lib/dirty_seed/assigners/dirty_boolean_spec.rb +13 -0
  105. data/spec/lib/dirty_seed/assigners/dirty_date_spec.rb +15 -0
  106. data/spec/lib/dirty_seed/assigners/dirty_float_spec.rb +47 -0
  107. data/spec/lib/dirty_seed/assigners/dirty_integer_spec.rb +49 -0
  108. data/spec/lib/dirty_seed/assigners/dirty_string_spec.rb +15 -0
  109. data/spec/lib/dirty_seed/assigners/dirty_time_spec.rb +15 -0
  110. data/spec/lib/dirty_seed/data_model_spec.rb +72 -0
  111. data/spec/lib/dirty_seed/dirty_association_spec.rb +64 -0
  112. data/spec/lib/dirty_seed/dirty_attribute_spec.rb +49 -0
  113. data/spec/lib/dirty_seed/dirty_model_spec.rb +102 -0
  114. data/spec/lib/dirty_seed/sorter_spec.rb +46 -0
  115. data/spec/lib/tasks/dirty_seed_tasks_spec.rb +21 -0
  116. data/spec/rails_helper.rb +44 -0
  117. data/spec/support/helpers.rb +30 -0
  118. metadata +282 -0
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ # Represents an Active Record association
5
+ class DirtyAssociation
6
+ extend ::DirtySeed::MethodMissingHelper
7
+ forward_missing_methods_to :reflections
8
+
9
+ attr_reader :dirty_model, :reflection
10
+
11
+ # Initializes an instance
12
+ # @param dirty_model [DirtySeed::DirtyModel]
13
+ # @param reflection [ActiveRecord::Reflection::BelongsToReflection]
14
+ # @return [DirtySeed::DirtyAssociation]
15
+ def initialize(dirty_model, reflection)
16
+ @dirty_model = dirty_model
17
+ @reflection = reflection
18
+ end
19
+
20
+ # Assigns a random value to the association
21
+ # @param instance [Object] an instance of a class inheriting from ApplicationRecord
22
+ # @return [void]
23
+ def assign_value(instance)
24
+ return if associated_models.empty?
25
+
26
+ instance.public_send(:"#{name}=", value)
27
+ rescue ArgumentError => e
28
+ @errors << e
29
+ end
30
+
31
+ # Returns a random instance matching the reflection
32
+ # @return [Object] an instance of a class inheriting from ApplicationRecord
33
+ def value
34
+ random_model = associated_models.sample
35
+ random_id = random_model.pluck(:id).sample
36
+ random_model.find_by(id: random_id)
37
+ end
38
+
39
+ # Returns the reflection name
40
+ # @return [String]
41
+ def name
42
+ reflection.name
43
+ end
44
+
45
+ # Returns the attribute containing the foreign key
46
+ # @return [Symbol]
47
+ def attribute
48
+ :"#{name}_id"
49
+ end
50
+
51
+ # Returns the attribute containing the foreign type (for polymorphic associations)
52
+ # @example
53
+ # Given Bar.belongs_to(:barable, polymorphic: true)
54
+ # And self.model == Bar
55
+ # Then it returns barable_type
56
+ # @return [Symbol]
57
+ def type_key
58
+ reflection.foreign_type&.to_sym
59
+ end
60
+
61
+ # Returns or defines associated_models
62
+ # @return [Array<Class>] a class inheriting from ApplicationRecord
63
+ def associated_models
64
+ polymorphic? ? polymorphic_associations : regular_associations
65
+ end
66
+
67
+ # Returns true if the reflection is polymorphic
68
+ # @example
69
+ # Given Bar.belongs_to(:barable, polymorphic: true)
70
+ # And self.model == Bar
71
+ # Then it returns true
72
+ # @return [Boolean]
73
+ def polymorphic?
74
+ reflection.options[:polymorphic]
75
+ end
76
+
77
+ private
78
+
79
+ # Returns the reflected models for a regular association
80
+ # @example
81
+ # Given Bar.belongs_to(:foo)
82
+ # And Foo.has_many(:bars)
83
+ # And self.model == Bar
84
+ # Then it returns [Foo]
85
+ # @return [Array<Class>] a class inheriting from ApplicationRecord
86
+ def regular_associations
87
+ [reflection.klass]
88
+ end
89
+
90
+ # Returns the reflected models for a polymorphic association
91
+ # @example
92
+ # Given Bar.belongs_to(:barable, polymorphic: true)
93
+ # And Foo.has_many(:bars, as: :barable)
94
+ # And Zed.has_many(:bars, as: :barable)
95
+ # And #model is Bar
96
+ # Then it returns [Foo, Zed]
97
+ # @return [Array<Class>] a class inheriting from ApplicationRecord
98
+ def polymorphic_associations
99
+ DirtySeed::DataModel.active_record_models.select do |active_record_model|
100
+ active_record_model.reflections.values.any? do |arm_reflection|
101
+ arm_reflection.options[:as]&.to_sym == name
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ # Represents an Active Record attribute
5
+ class DirtyAttribute
6
+ extend ::DirtySeed::MethodMissingHelper
7
+ forward_missing_methods_to :column
8
+
9
+ attr_reader :dirty_model, :column
10
+
11
+ # Initializes an instance
12
+ # @param dirty_model [DirtySeed::DirtyModel]
13
+ # @param column [ActiveRecord::ConnectionAdapters::Column]
14
+ # @return [DirtySeed::DirtyAttribute]
15
+ def initialize(dirty_model, column)
16
+ @dirty_model = dirty_model
17
+ @column = column
18
+ end
19
+
20
+ # Assigns a value to the attribute
21
+ # @param instance [Object] an instance of a class inheriting from ApplicationRecord
22
+ # @param sequence [Integer]
23
+ # @return [void]
24
+ def assign_value(instance, sequence)
25
+ instance.assign_attributes(name => value(sequence))
26
+ rescue ArgumentError => e
27
+ dirty_model.errors << e
28
+ end
29
+
30
+ # Returns a value matching type and validators
31
+ # @param sequence [Integer]
32
+ # @return [Object, nil]
33
+ def value(sequence)
34
+ assigner = "DirtySeed::Assigners::Dirty#{type.capitalize}".constantize
35
+ assigner.new(self, sequence).value
36
+ # If attribute type is not currently handled (json, array...) return nil
37
+ rescue NameError
38
+ nil
39
+ end
40
+
41
+ # Returns attribute name
42
+ # @return [Symbol]
43
+ def name
44
+ column.name.to_sym
45
+ end
46
+
47
+ # Returns attribute type
48
+ # @return [Symbol]
49
+ def type
50
+ return :float if column.sql_type_metadata.type == :decimal
51
+ return :time if column.sql_type_metadata.type == :datetime
52
+
53
+ column.sql_type_metadata.type
54
+ end
55
+
56
+ # Returns an validators related to the current attribute
57
+ # @return [Array<ActiveModel::Validations::EachValidators>]
58
+ def validators
59
+ dirty_model.validators.select do |validator|
60
+ validator.attributes.include? name
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ # Represents an Active Record model
5
+ class DirtyModel
6
+ extend ::DirtySeed::MethodMissingHelper
7
+ forward_missing_methods_to :model
8
+
9
+ attr_reader :model, :seeded
10
+ attr_writer :errors
11
+
12
+ PROTECTED_COLUMNS = %w[
13
+ id
14
+ type
15
+ created_at
16
+ updated_at
17
+ encrypted_password
18
+ reset_password_token
19
+ reset_password_sent_at
20
+ remember_created_at
21
+ ].freeze
22
+ private_constant :PROTECTED_COLUMNS
23
+
24
+ # Initializes an instance
25
+ # @param model [Class] a class inheriting from ApplicationRecord
26
+ # @return [DirtySeed::DirtyModel]
27
+ def initialize(model)
28
+ @model = model
29
+ end
30
+
31
+ # Returns models where models are associated to the current model through a has_many or has_one associations
32
+ # @return [Array<Class>] ActiveRecord models
33
+ def associated_models
34
+ associations.map(&:associated_models).flatten
35
+ end
36
+
37
+ # Returns an dirty associations representing the self.model belongs_to associations
38
+ # @return [Array<DirtySeed::DirtyAssociation>]
39
+ def associations
40
+ included_reflections.map do |reflection|
41
+ DirtySeed::DirtyAssociation.new(self, reflection)
42
+ end
43
+ end
44
+
45
+ # Returns model attributes
46
+ # @return [Array<String>]
47
+ def attributes
48
+ included_columns.map do |column|
49
+ DirtySeed::DirtyAttribute.new(self, column)
50
+ end
51
+ end
52
+
53
+ # Returns uniq errors
54
+ # @return [Array<Error>]
55
+ def errors
56
+ @errors.flatten.uniq
57
+ end
58
+
59
+ # Creates instances for each model
60
+ # @param count [Integer]
61
+ # @return [void]
62
+ def seed(count = 5)
63
+ reset_info
64
+ count.times do |sequence|
65
+ create_instance(sequence)
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ # Reset seed info
72
+ # @return [void]
73
+ def reset_info
74
+ @seeded = 0
75
+ @errors = []
76
+ end
77
+
78
+ # Creates an instance
79
+ # @param sequence [Integer]
80
+ # @return [void]
81
+ def create_instance(sequence)
82
+ instance = model.new
83
+ associations.each { |association| association.assign_value(instance) }
84
+ attributes.each { |attribute| attribute.assign_value(instance, sequence) }
85
+ if instance.save
86
+ @seeded += 1
87
+ else
88
+ @errors << instance.errors.full_messages
89
+ end
90
+ rescue ActiveRecord::ActiveRecordError => e
91
+ errors << e
92
+ end
93
+
94
+ # Returns columns that should be treated as regular attributes
95
+ # @return [Array<ActiveRecord::ConnectionAdapters::Column>]
96
+ def included_columns
97
+ excluded = PROTECTED_COLUMNS + reflection_related_attributes
98
+ model.columns.reject do |column|
99
+ column.name.in? excluded
100
+ end
101
+ end
102
+
103
+ # Returns attributes related to an association
104
+ # @example
105
+ # ["foo_id", "doable_id", "doable_type"]
106
+ # @return [Array<String>]
107
+ def reflection_related_attributes
108
+ all_reflection_related_attributes =
109
+ associations.map do |association|
110
+ [association.attribute, association.type_key].compact
111
+ end
112
+ all_reflection_related_attributes.flatten.map(&:to_s)
113
+ end
114
+
115
+ # Returns reflections of the model
116
+ # @return [Array<ActiveRecord::Reflection::BelongsToReflection>]
117
+ def included_reflections
118
+ model.reflections.values.select do |reflection|
119
+ reflection.is_a? ActiveRecord::Reflection::BelongsToReflection
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ class Engine < ::Rails::Engine
5
+ isolate_namespace DirtySeed
6
+
7
+ config.generators do |generators|
8
+ generators.test_framework :rspec
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ class Error < StandardError; end
5
+ class CyclicalAssociationsError < StandardError; end
6
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ # Forwards missing method to another object if it matches
5
+ module MethodMissingHelper
6
+ # Defines missing_method and respond_to_missing? methods
7
+ # @param addressee_key [Object]
8
+ # @return [Object]
9
+ # @raise [NoMethodError]
10
+ def forward_missing_methods_to(addressee_key)
11
+ define_addressee(addressee_key)
12
+ define_method_missing
13
+ define_respond_to_missing?
14
+ end
15
+
16
+ # Defines addressee method
17
+ # @param addressee_key [Object]
18
+ # @return [void]
19
+ def define_addressee(addressee_key)
20
+ define_method :addressee do
21
+ public_send(addressee_key)
22
+ end
23
+ end
24
+
25
+ # Defines missing_method method so it returns the adressee or calls super
26
+ # @example
27
+ # calling #name on a DirtyModel instance will call name on its @model object
28
+ # @return [void]
29
+ def define_method_missing
30
+ define_method :method_missing do |method_name, *args, &block|
31
+ return super(method_name, *args, &block) unless addressee.respond_to?(method_name)
32
+
33
+ addressee.public_send(method_name, *args, &block)
34
+ end
35
+ end
36
+
37
+ # Defines respond_to_missing? method to matches the method_missing behavior
38
+ # @return [void]
39
+ def define_respond_to_missing?
40
+ define_method :respond_to_missing? do |method_name, _include_private = false|
41
+ # :nocov:
42
+ return super(method_name, _include_private = false) unless addressee.respond_to?(method_name)
43
+
44
+ true
45
+ # :nocov:
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DirtySeed
4
+ # Sorts ActiveRecord models depending on their associations
5
+ class Sorter
6
+ attr_reader :models, :sorted, :checked, :current, :skip_optional
7
+ alias unsorted models
8
+
9
+ # Initializes an instance
10
+ # @param models [Array<Class>] models inheriting from ActiveRecord::Base
11
+ # @return [DirtySeed::Sorter]
12
+ def initialize(models = [])
13
+ @models = models
14
+ @sorted = []
15
+ @checked = []
16
+ @current = unsorted.first
17
+ end
18
+
19
+ # Sorts models depending on their associations
20
+ # @return [Array<Class>] classes inheriting from ActiveRecord::Base
21
+ def sort!
22
+ return sorted if unsorted.empty?
23
+
24
+ set_current
25
+ # active skip_optional option to prevent infinite loop
26
+ skip_optional! if break_loop?
27
+ insert_or_rotate
28
+ sort!
29
+ end
30
+
31
+ private
32
+
33
+ # Defines the current model to be sorted and add it to the checked ones
34
+ # @return [Class] class inheriting from ActiveRecord::Base
35
+ def set_current
36
+ @current = unsorted.first
37
+ checked << current
38
+ end
39
+
40
+ # Returns true if the current model has already been checked and skip optional option is not already activated
41
+ # @return [Boolean]
42
+ def break_loop?
43
+ current.in?(checked) && !skip_optional
44
+ end
45
+
46
+ # Activates skip_optional option to prevent infinite loop
47
+ # @return [void]
48
+ def skip_optional!
49
+ # if skip_optional is already true
50
+ # there is an infinite loop of belongs_to associations
51
+ raise DirtySeed::CyclicalAssociationsError if skip_optional
52
+
53
+ @skip_optional = true
54
+ @checked = []
55
+ end
56
+
57
+ # Chooses if current should be added to sorted ones or not
58
+ # @return [void]
59
+ def insert_or_rotate
60
+ # if the current is dependent form a non-sorted model
61
+ if dependent?
62
+ # rotate models array so current will be sorted at the end
63
+ unsorted.rotate!
64
+ else
65
+ # removed current from unsorted and add it to sorted
66
+ sorted << unsorted.shift
67
+ end
68
+ end
69
+
70
+ # Returns true if @current belongs_to a model that has not been sorted yet
71
+ # @return [Boolean]
72
+ def dependent?
73
+ return false if unsorted.one?
74
+
75
+ current.reflections.values.any? do |reflection|
76
+ belongs_to?(reflection) &&
77
+ unsorted.any? do |model|
78
+ mirror?(model, reflection)
79
+ end
80
+ end
81
+ end
82
+
83
+ # Returns true if relfection is a :belongs_to kind
84
+ # @param reflection [ActiveRecord::Reflection::AssociationReflection]
85
+ # @return [Boolean]
86
+ def belongs_to?(reflection)
87
+ return false if reflection.options[:optional] && skip_optional
88
+
89
+ reflection.is_a?(ActiveRecord::Reflection::BelongsToReflection)
90
+ end
91
+
92
+ # Returns true if model is or can be the <reflection> mirror
93
+ # @param model [ActiveRecord model]
94
+ # @param reflection [ActiveRecord::Reflection::AssociationReflection]
95
+ # @example
96
+ # Given `Foo.belongs_to(:bar)`
97
+ # And `Bar.has_many(:foos)`
98
+ # And <reflection> is the belongs_to reflection
99
+ # Then mirror?(Bar, reflection) returns true
100
+ # @example
101
+ # Given `Foo.belongs_to(:foable, polymorphic: true)`
102
+ # And `Bar.has_many(:foos, as: :foable)`
103
+ # And `Baz.has_many(:foos, as: :foable)`
104
+ # And <reflection> is the Foo "belongs_to" reflection
105
+ # Then mirror?(Bar, reflection) returns true
106
+ # And mirror?(Baz, reflection) returns true
107
+ # @return [Boolean]
108
+ def mirror?(model, reflection)
109
+ if reflection.options[:polymorphic]
110
+ model.reflections.values.any? do |model_reflection|
111
+ model_reflection.options[:as] == reflection.name
112
+ end
113
+ else
114
+ model == reflection.klass
115
+ end
116
+ end
117
+ end
118
+ end