edge_rider 1.1.0 → 2.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/.github/workflows/test.yml +99 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +16 -6
- data/Gemfile +1 -0
- data/Gemfile.4.2.mysql2 +2 -2
- data/Gemfile.4.2.mysql2.lock +20 -20
- data/Gemfile.4.2.pg +1 -1
- data/Gemfile.4.2.pg.lock +18 -18
- data/Gemfile.5.2.mysql2 +2 -2
- data/Gemfile.5.2.mysql2.lock +6 -6
- data/Gemfile.5.2.pg +1 -1
- data/Gemfile.5.2.pg.lock +4 -4
- data/{Gemfile.6.0.pg → Gemfile.6.1.pg} +2 -2
- data/Gemfile.6.1.pg.lock +78 -0
- data/Gemfile.lock +1 -0
- data/README.md +84 -60
- data/edge_rider.gemspec +24 -16
- data/lib/edge_rider/util.rb +1 -1
- data/lib/edge_rider/version.rb +1 -1
- metadata +13 -24
- data/.travis.yml +0 -51
- data/Gemfile.3.2.mysql2 +0 -17
- data/Gemfile.3.2.mysql2.lock +0 -72
- data/Gemfile.6.0.pg.lock +0 -74
- data/spec/edge_rider/collect_column_spec.rb +0 -85
- data/spec/edge_rider/collect_ids_spec.rb +0 -108
- data/spec/edge_rider/origin_class_spec.rb +0 -32
- data/spec/edge_rider/preload_associations_spec.rb +0 -31
- data/spec/edge_rider/scoped_spec.rb +0 -53
- data/spec/edge_rider/to_id_query_spec.rb +0 -29
- data/spec/edge_rider/traverse_association_spec.rb +0 -175
- data/spec/edge_rider/util_spec.rb +0 -5
- data/spec/spec_helper.rb +0 -14
- data/spec/support/database.rb +0 -39
- data/spec/support/database.sample.yml +0 -10
- data/spec/support/database.travis.yml +0 -9
- data/spec/support/models.rb +0 -97
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe EdgeRider::PreloadAssociations do
|
4
|
-
|
5
|
-
describe '.preload_associations' do
|
6
|
-
it 'should preload the given named associations so they are no longer fetched lazily' do
|
7
|
-
forum = Forum.create!
|
8
|
-
topic = Topic.create!(forum: forum)
|
9
|
-
post = Post.create!(topic: topic)
|
10
|
-
|
11
|
-
Forum.preload_associations([forum], topics: :posts)
|
12
|
-
Topic.should_not_receive(:new)
|
13
|
-
Post.should_not_receive(:new)
|
14
|
-
forum.topics.collect(&:posts)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '#preload_associations' do
|
19
|
-
it 'should preload the given named associations so they are no longer fetched lazily' do
|
20
|
-
forum = Forum.create!
|
21
|
-
topic = Topic.create!(forum: forum)
|
22
|
-
post = Post.create!(topic: topic)
|
23
|
-
|
24
|
-
forum.preload_associations(topics: :posts)
|
25
|
-
Topic.should_not_receive(:new)
|
26
|
-
Post.should_not_receive(:new)
|
27
|
-
forum.topics.collect(&:posts)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe EdgeRider::Scoped do
|
4
|
-
describe 'scoped' do
|
5
|
-
|
6
|
-
it 'returns a scope when called without parameters' do
|
7
|
-
EdgeRider::Util.scope?( Forum.scoped ).should == true
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'returns a scope when called with an empty hash' do
|
11
|
-
EdgeRider::Util.scope?( Forum.scoped({}) ).should == true
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'respects conditions' do
|
15
|
-
trashed = Forum.create! trashed: true
|
16
|
-
active = Forum.create! trashed: false
|
17
|
-
|
18
|
-
Forum.scoped(conditions: { trashed: true }).to_a.should == [ trashed ]
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'respects order' do
|
22
|
-
c = Forum.create! name: 'Chemikalien'
|
23
|
-
a = Forum.create! name: 'Allegorie'
|
24
|
-
b = Forum.create! name: 'Botanisch'
|
25
|
-
|
26
|
-
Forum.scoped(order: 'name ASC').to_a.should == [ a, b, c ]
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'can be used to add conditions to an existing scope chain' do
|
30
|
-
bulldog = Forum.create! name: 'bulldog', trashed: false
|
31
|
-
trashed = Forum.create! name: 'maneuver', trashed: true
|
32
|
-
trashed_bulldog = Forum.create! name: 'bulldog', trashed: true
|
33
|
-
|
34
|
-
Forum.
|
35
|
-
scoped(conditions: { trashed: true }).
|
36
|
-
scoped(conditions: { name: 'bulldog' }).to_a.should == [ trashed_bulldog ]
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'can be used to add conditions to a has_many association' do
|
40
|
-
forum = Forum.create!
|
41
|
-
thema = Topic.create! subject: 'Thema', trashed: false, forum: forum
|
42
|
-
other_topic = Topic.create! subject: 'Other', trashed: false, forum: forum
|
43
|
-
trashed_thema = Topic.create! subject: 'Thema', trashed: true, forum: forum
|
44
|
-
|
45
|
-
has_many_scope = forum.active_topics
|
46
|
-
# In Rails 3, #scoped on associations does not take parameters but turns
|
47
|
-
# an association into a real scope.
|
48
|
-
has_many_scope = has_many_scope.scoped if ActiveRecord::VERSION::MAJOR == 3
|
49
|
-
has_many_scope.scoped(conditions: { subject: 'Thema' }).to_a.should =~ [ thema ]
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe EdgeRider::ToIdQuery do
|
4
|
-
|
5
|
-
describe '#to_id_query' do
|
6
|
-
|
7
|
-
it 'should simplify a scope to a IN query that selects IDs' do
|
8
|
-
Forum.create!(id: 1, name: 'Name 1')
|
9
|
-
Forum.create!(id: 2, name: 'Name 2')
|
10
|
-
Forum.create!(id: 3, name: 'Name 2')
|
11
|
-
scope = Forum.scoped(conditions: { name: 'Name 2' })
|
12
|
-
scope.to_id_query.to_sql.should =~ EdgeRider::Development.selects_star_with_conditions_pattern('forums', /["`]?forums["`]?\.["`]?id["`]? IN \(2,\s*3\)/)
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'should resolve and lose any JOINs' do
|
16
|
-
Forum.create!(id: 1, name: 'A')
|
17
|
-
Forum.create!(id: 2, name: 'B')
|
18
|
-
Forum.create!(id: 3, name: 'A')
|
19
|
-
Topic.create!(id: 100, forum_id: 1)
|
20
|
-
Topic.create!(id: 101, forum_id: 1)
|
21
|
-
Topic.create!(id: 102, forum_id: 2)
|
22
|
-
Topic.create!(id: 103, forum_id: 3)
|
23
|
-
scope = Topic.scoped(joins: :forum, conditions: "forums.name = 'A'")
|
24
|
-
scope.to_id_query.to_sql.should =~ EdgeRider::Development.selects_star_with_conditions_pattern('topics', /["`]?topics["`]?\.["`]?id["`]? IN \(100,\s*101,\s*103\)/)
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
end
|
@@ -1,175 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe EdgeRider::TraverseAssociation do
|
4
|
-
|
5
|
-
describe '#traverse_association' do
|
6
|
-
|
7
|
-
it 'should traverse a belongs_to associations' do
|
8
|
-
forum_1 = Forum.create!
|
9
|
-
forum_2 = Forum.create!
|
10
|
-
forum_3 = Forum.create!
|
11
|
-
topic_1 = Topic.create!(forum: forum_1)
|
12
|
-
topic_2 = Topic.create!(forum: forum_1)
|
13
|
-
topic_3 = Topic.create!(forum: forum_2)
|
14
|
-
topic_4 = Topic.create!(forum: forum_3)
|
15
|
-
scope = Topic.scoped(conditions: { id: [ topic_2.id, topic_4.id ] })
|
16
|
-
traversed_scope = scope.traverse_association(:forum)
|
17
|
-
EdgeRider::Util.scope?(traversed_scope).should == true
|
18
|
-
traversed_scope.to_a.should =~ [forum_1, forum_3]
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'should raise an error when traversing a belongs_to association with conditions, until this is implemented' do
|
22
|
-
forum = Forum.create!(trashed: true)
|
23
|
-
topic = Topic.create(forum: forum)
|
24
|
-
|
25
|
-
scope = Topic.scoped(conditions: { id: topic.id })
|
26
|
-
expect { scope.traverse_association(:active_forum) }.to raise_error(NotImplementedError)
|
27
|
-
end
|
28
|
-
|
29
|
-
it 'should traverse multiple belongs_to associations in different model classes' do
|
30
|
-
forum_1 = Forum.create!
|
31
|
-
forum_2 = Forum.create!
|
32
|
-
forum_3 = Forum.create!
|
33
|
-
topic_1 = Topic.create!(forum: forum_1)
|
34
|
-
topic_2 = Topic.create!(forum: forum_2)
|
35
|
-
topic_3 = Topic.create!(forum: forum_3)
|
36
|
-
post_1 = Post.create!(topic: topic_1)
|
37
|
-
post_2 = Post.create!(topic: topic_2)
|
38
|
-
post_3 = Post.create!(topic: topic_3)
|
39
|
-
scope = Post.scoped(conditions: { id: [post_1.id, post_3.id] })
|
40
|
-
traversed_scope = scope.traverse_association(:topic, :forum)
|
41
|
-
EdgeRider::Util.scope?(traversed_scope).should == true
|
42
|
-
traversed_scope.to_a.should =~ [forum_1, forum_3]
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should traverse one or more has_many associations' do
|
46
|
-
forum_1 = Forum.create!
|
47
|
-
forum_2 = Forum.create!
|
48
|
-
forum_3 = Forum.create!
|
49
|
-
topic_1 = Topic.create!(forum: forum_1)
|
50
|
-
topic_2 = Topic.create!(forum: forum_2)
|
51
|
-
topic_3 = Topic.create!(forum: forum_3)
|
52
|
-
post_1 = Post.create!(topic: topic_1)
|
53
|
-
post_2 = Post.create!(topic: topic_2)
|
54
|
-
post_3a = Post.create!(topic: topic_3)
|
55
|
-
post_3b = Post.create!(topic: topic_3)
|
56
|
-
scope = Forum.scoped(conditions: { id: [forum_1.id, forum_3.id] })
|
57
|
-
traversed_scope = scope.traverse_association(:topics, :posts)
|
58
|
-
EdgeRider::Util.scope?(traversed_scope).should == true
|
59
|
-
traversed_scope.to_a.should =~ [post_1, post_3a, post_3b]
|
60
|
-
end
|
61
|
-
|
62
|
-
# in Rails 4, conditions on a scope are expressed as a lambda parameter
|
63
|
-
it 'should raise an error when traversing a has_many association with conditions, until this is implemented' do
|
64
|
-
forum = Forum.create!
|
65
|
-
topic = Topic.create(forum: forum, trashed: true)
|
66
|
-
|
67
|
-
scope = Forum.scoped(conditions: { id: forum.id })
|
68
|
-
expect { scope.traverse_association(:active_topics) }.to raise_error(NotImplementedError)
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'should traverse a has_many :through association' do
|
72
|
-
forum_1 = Forum.create!
|
73
|
-
forum_2 = Forum.create!
|
74
|
-
forum_3 = Forum.create!
|
75
|
-
topic_1 = Topic.create!(forum: forum_1)
|
76
|
-
topic_2 = Topic.create!(forum: forum_2)
|
77
|
-
topic_3 = Topic.create!(forum: forum_3)
|
78
|
-
post_1 = Post.create!(topic: topic_1)
|
79
|
-
post_2 = Post.create!(topic: topic_2)
|
80
|
-
post_3a = Post.create!(topic: topic_3)
|
81
|
-
post_3b = Post.create!(topic: topic_3)
|
82
|
-
scope = Forum.scoped(conditions: { id: [forum_1.id, forum_3.id] })
|
83
|
-
traversed_scope = scope.traverse_association(:posts)
|
84
|
-
EdgeRider::Util.scope?(traversed_scope).should == true
|
85
|
-
traversed_scope.to_a.should =~ [post_1, post_3a, post_3b]
|
86
|
-
end
|
87
|
-
|
88
|
-
it 'should traverse a has_one association' do
|
89
|
-
user_1 = User.create!
|
90
|
-
user_2 = User.create!
|
91
|
-
user_3 = User.create!
|
92
|
-
profile_1 = Profile.create!(user: user_1)
|
93
|
-
profile_2 = Profile.create!(user: user_2)
|
94
|
-
profile_3 = Profile.create!(user: user_3)
|
95
|
-
scope = User.scoped(conditions: { id: [user_2.id, user_3.id] })
|
96
|
-
traversed_scope = scope.traverse_association(:profile)
|
97
|
-
EdgeRider::Util.scope?(traversed_scope).should == true
|
98
|
-
traversed_scope.to_a.should =~ [profile_2, profile_3]
|
99
|
-
end
|
100
|
-
|
101
|
-
it 'should raise an error when traversing a has_many association with conditions, until this is implemented' do
|
102
|
-
user = User.create!
|
103
|
-
profile = Profile.create(user: user, trashed: true)
|
104
|
-
|
105
|
-
scope = User.scoped(conditions: { id: user.id })
|
106
|
-
expect { scope.traverse_association(:active_profile) }.to raise_error(NotImplementedError)
|
107
|
-
end
|
108
|
-
|
109
|
-
it 'should traverse up and down the same edges' do
|
110
|
-
forum_1 = Forum.create!
|
111
|
-
forum_2 = Forum.create!
|
112
|
-
forum_3 = Forum.create!
|
113
|
-
topic_1 = Topic.create!(forum: forum_1)
|
114
|
-
topic_2 = Topic.create!(forum: forum_2)
|
115
|
-
topic_3 = Topic.create!(forum: forum_3)
|
116
|
-
post_1 = Post.create!(topic: topic_1)
|
117
|
-
post_2 = Post.create!(topic: topic_2)
|
118
|
-
post_3a = Post.create!(topic: topic_3)
|
119
|
-
post_3b = Post.create!(topic: topic_3)
|
120
|
-
scope = Post.scoped(conditions: { id: [post_3a.id] })
|
121
|
-
traversed_scope = scope.traverse_association(:topic, :forum, :topics, :posts)
|
122
|
-
EdgeRider::Util.scope?(traversed_scope).should == true
|
123
|
-
traversed_scope.to_a.should =~ [post_3a, post_3b]
|
124
|
-
end
|
125
|
-
|
126
|
-
it 'should traverse to a polymorphic has one association' do
|
127
|
-
profile = Profile.create!
|
128
|
-
profile_attachment = Attachment.create!(record: profile)
|
129
|
-
|
130
|
-
# Sanity check that the condition includes both record id and record type
|
131
|
-
Attachment.create!(record_id: profile_attachment.id, record_type: 'NonExisting')
|
132
|
-
|
133
|
-
scope = Profile.scoped(conditions: { id: [profile.id] })
|
134
|
-
scope.traverse_association(:attachment).to_a.should =~ [profile_attachment]
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'should traverse to a polymorphic has many association' do
|
138
|
-
topic = Topic.create!
|
139
|
-
topic_attachment_1 = Attachment.create!(record: topic)
|
140
|
-
topic_attachment_2 = Attachment.create!(record: topic)
|
141
|
-
|
142
|
-
# Sanity check that the condition includes both record id and record type
|
143
|
-
Attachment.create!(record_id: topic_attachment_1.id, record_type: 'NonExisting')
|
144
|
-
|
145
|
-
scope = Topic.scoped(conditions: { id: [topic_attachment_1.id, topic_attachment_2.id] })
|
146
|
-
scope.traverse_association(:attachments).to_a.should =~ [topic_attachment_1, topic_attachment_2]
|
147
|
-
end
|
148
|
-
|
149
|
-
it 'should raise an error if you want to traverse from a polymorphic association' do
|
150
|
-
profile = Profile.create!
|
151
|
-
profile_attachment = Attachment.create!(record: profile)
|
152
|
-
|
153
|
-
scope = Attachment.scoped(conditions: { id: [profile_attachment.id] })
|
154
|
-
|
155
|
-
if [4, 3].include?(EdgeRider::Util.active_record_version)
|
156
|
-
expect { scope.traverse_association(:record) }.to raise_error(
|
157
|
-
NameError,
|
158
|
-
'uninitialized constant Attachment::Record'
|
159
|
-
)
|
160
|
-
elsif EdgeRider::Util.active_record_version == 5
|
161
|
-
expect { scope.traverse_association(:record) }.to raise_error(
|
162
|
-
ArgumentError,
|
163
|
-
'Polymorphic association does not support to compute class.'
|
164
|
-
)
|
165
|
-
else
|
166
|
-
expect { scope.traverse_association(:record) }.to raise_error(
|
167
|
-
ArgumentError,
|
168
|
-
'Polymorphic associations do not support computing the class.'
|
169
|
-
)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
end
|
174
|
-
|
175
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
$: << File.join(File.dirname(__FILE__), "/../lib" )
|
2
|
-
|
3
|
-
require 'edge_rider'
|
4
|
-
require 'edge_rider/development'
|
5
|
-
require 'database_cleaner'
|
6
|
-
require 'gemika'
|
7
|
-
require 'pry'
|
8
|
-
require 'byebug'
|
9
|
-
|
10
|
-
# Requires supporting files with custom matchers and macros, etc in ./support/ and its subdirectories.
|
11
|
-
Dir["#{File.dirname(__FILE__)}/support/*.rb"].sort.each {|f| require f}
|
12
|
-
|
13
|
-
Gemika::RSpec.configure_clean_database_before_example
|
14
|
-
Gemika::RSpec.configure_should_syntax
|
data/spec/support/database.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
Gemika::Database.new.rewrite_schema! do
|
2
|
-
|
3
|
-
create_table :forums do |t|
|
4
|
-
t.string :name
|
5
|
-
t.boolean :trashed
|
6
|
-
end
|
7
|
-
|
8
|
-
create_table :topics do |t|
|
9
|
-
t.string :subject
|
10
|
-
t.references :forum
|
11
|
-
t.references :author
|
12
|
-
t.boolean :trashed
|
13
|
-
end
|
14
|
-
|
15
|
-
create_table :posts do |t|
|
16
|
-
t.text :body
|
17
|
-
t.references :topic
|
18
|
-
t.references :author
|
19
|
-
t.boolean :trashed
|
20
|
-
t.timestamps null: true
|
21
|
-
end
|
22
|
-
|
23
|
-
create_table :users do |t|
|
24
|
-
t.string :email
|
25
|
-
t.boolean :trashed
|
26
|
-
end
|
27
|
-
|
28
|
-
create_table :profiles do |t|
|
29
|
-
t.references :user
|
30
|
-
t.text :hobbies
|
31
|
-
t.boolean :trashed
|
32
|
-
end
|
33
|
-
|
34
|
-
create_table :attachments do |t|
|
35
|
-
t.string :record_type
|
36
|
-
t.integer :record_id
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
data/spec/support/models.rb
DELETED
@@ -1,97 +0,0 @@
|
|
1
|
-
require 'has_defaults'
|
2
|
-
|
3
|
-
# Since our specs are mostly about working with IDs, this module can be
|
4
|
-
# included in an ActiveRecord model class to allow setting the :id attribute
|
5
|
-
# on create. This is forbidden by default.
|
6
|
-
# http://stackoverflow.com/questions/431617/overriding-id-on-create-in-activerecord
|
7
|
-
module AllowSettingIdOnCreate
|
8
|
-
|
9
|
-
module RemoveIdFromProtectedAttributes
|
10
|
-
def attributes_protected_by_default
|
11
|
-
super - ['id']
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.included(base)
|
16
|
-
base.send(:extend, RemoveIdFromProtectedAttributes)
|
17
|
-
end
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
class Forum < ActiveRecord::Base
|
25
|
-
include AllowSettingIdOnCreate
|
26
|
-
|
27
|
-
has_many :topics
|
28
|
-
has_many :posts, through: :topics
|
29
|
-
EdgeRider::Util.define_association self, :has_many, :active_topics,
|
30
|
-
conditions: { trashed: false }, class_name: 'Topic'
|
31
|
-
|
32
|
-
has_defaults trashed: false
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
class Post < ActiveRecord::Base
|
38
|
-
include AllowSettingIdOnCreate
|
39
|
-
|
40
|
-
belongs_to :topic
|
41
|
-
belongs_to :author, class_name: 'User'
|
42
|
-
|
43
|
-
has_defaults trashed: false
|
44
|
-
|
45
|
-
EdgeRider::Util.define_scope self, :these, lambda { |array| { conditions: { id: array } } }
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
class Profile < ActiveRecord::Base
|
51
|
-
include AllowSettingIdOnCreate
|
52
|
-
|
53
|
-
belongs_to :user
|
54
|
-
has_one :attachment, as: :record
|
55
|
-
|
56
|
-
has_defaults trashed: false
|
57
|
-
|
58
|
-
end
|
59
|
-
|
60
|
-
|
61
|
-
class Topic < ActiveRecord::Base
|
62
|
-
include AllowSettingIdOnCreate
|
63
|
-
|
64
|
-
belongs_to :forum
|
65
|
-
EdgeRider::Util.define_association self, :belongs_to, :active_forum,
|
66
|
-
conditions: { trashed: false }, class_name: 'Forum'
|
67
|
-
|
68
|
-
has_many :posts
|
69
|
-
belongs_to :author, class_name: 'User'
|
70
|
-
has_many :post_authors, through: :posts
|
71
|
-
has_many :attachments, as: :record
|
72
|
-
|
73
|
-
has_defaults trashed: false
|
74
|
-
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
class User < ActiveRecord::Base
|
79
|
-
include AllowSettingIdOnCreate
|
80
|
-
|
81
|
-
has_many :posts
|
82
|
-
has_many :topics
|
83
|
-
|
84
|
-
has_one :profile
|
85
|
-
EdgeRider::Util.define_association self, :has_one, :active_profile,
|
86
|
-
conditions: { trashed: false }, class_name: 'Profile'
|
87
|
-
|
88
|
-
has_defaults trashed: false
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
class Attachment < ActiveRecord::Base
|
94
|
-
|
95
|
-
belongs_to :record, polymorphic: true
|
96
|
-
|
97
|
-
end
|