has-many-with-set 1.3.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{README.textile → README.md} +31 -26
- data/lib/generators/has_many_with_set/templates/sets.rb.erb +1 -1
- data/lib/has-many-with-set/accessors.rb +19 -18
- data/lib/has-many-with-set/callbacks.rb +6 -6
- data/lib/has-many-with-set/has-many-with-set.rb +3 -3
- data/lib/has-many-with-set/queries.rb +1 -1
- data/lib/has-many-with-set/relationships.rb +5 -5
- data/lib/has-many-with-set/version.rb +1 -1
- data/test/has-many-with-set_test.rb +46 -53
- data/test/support/models.rb +7 -3
- data/test/support/prepare_activerecord.rb +11 -11
- data/test/tmp/db/migrate/20180923002305_create_ones_twos_set.rb +18 -0
- metadata +9 -9
- data/test/tmp/db/migrate/20141013205312_create_model_ones_model_twos_set.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a6605618e3038cc34da96f01c5a8acd806516ba9f41b901385a52a0e4ce14a6d
|
4
|
+
data.tar.gz: 827199a3b87007de3394f4bee41432820748c93019a7a0b660ff9980b338e35e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a4e622a55e2d219bb8011409aa3417ed045cb2d1e469ecd30fe55bccb57fcc59f012e736835f384184c749e9f68b88416dca21a3d960515ccb40d8d7ba59464
|
7
|
+
data.tar.gz: '0294441d7ecb4b6aed65c5d347bf42a94e11a87736e6f92ecfcb87ae3bf7dc46cbde2502411a52c383a152a3f33bf5cefb321b2359925ec2b082609cd7d4ae56'
|
@@ -1,16 +1,16 @@
|
|
1
|
-
|
1
|
+
# has-many-with-set
|
2
2
|
|
3
|
-
|
3
|
+
### A smarter way of doing many-to-many relationships in Ruby On Rails.
|
4
4
|
|
5
|
-
|
5
|
+
## Introduction
|
6
6
|
|
7
|
-
*Update: Now works with Rails
|
7
|
+
*Update: Now works with Rails 5*
|
8
8
|
|
9
9
|
Rails has two ways to model many-to-many relationships: *_has_and_belongs_to_many_* and *_has_many :through_*, this gem introduces a third one: *_has_many_with_set_*.
|
10
10
|
|
11
11
|
*_has_many_with_set_* is equivalent to *_has_and_belongs_to_many_* in functionality. It works only when you do not want information about a relationship but the relationship itself, behind the curtains though, they do not work anything alike, *_has_many_with_set_* is far more efficient in terms of data size as it reduces the redundancy that occurs in a normal many-to-many relationship when the cardinality is low, that is, the same combination occurs many times. For example, in a blog application, when many posts share the same tags.
|
12
12
|
|
13
|
-
|
13
|
+
## How so?
|
14
14
|
|
15
15
|
The regular way of doing many-to-many relationships is using a join table to relate two tables, both ways of doing it in Ruby On Rails use this method, the only difference is the degree of control they give you on the "intermediary" table, one hides it from you (which is nice) and the other allows you to put more data in it besides the relationship, use validations, callbacks, etc.
|
16
16
|
|
@@ -18,7 +18,8 @@ The _join_ table model is a very redundant way of storing these relationships if
|
|
18
18
|
|
19
19
|
For example:
|
20
20
|
|
21
|
-
|
21
|
+
```
|
22
|
+
Tag.create(:name => 'programming')
|
22
23
|
Tag.create(:name => 'open source')
|
23
24
|
Tag.create(:name => 'startups')
|
24
25
|
Tag.create(:name => 'ruby')
|
@@ -35,12 +36,13 @@ tags = Tag.all
|
|
35
36
|
a.save
|
36
37
|
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
ArticlesTagsSetsTag = Class.new(ApplicationRecord)
|
40
|
+
ArticlesTagsSetsTag.count # this class doesn't exist by default,
|
41
|
+
# I had to create it by hand for the example.
|
41
42
|
=> 1932
|
43
|
+
```
|
42
44
|
|
43
|
-
|
45
|
+
So we create five tags, and we create 1000 articles with a random combination of tags, not surprisingly, our join table has plenty of rows to represent all the relationships between our articles and their tags, if this were to behave linearly, if we had 1,000,000 articles we would have 1,932,000 rows just to represent the relationship.
|
44
46
|
|
45
47
|
This example (albeit a bit unrealistic) shows how redundant this is, even though we are using the same combination of tags over and over again we get more and more rows, if we are speaking about thousands it is not a big problem but when your databases grow to the hundreds of thousands or the millions, stuff like this starts to matter.
|
46
48
|
|
@@ -48,42 +50,45 @@ This is what this gem fixes, it makes sure that when you create a combination of
|
|
48
50
|
|
49
51
|
*_has-many-with-set_* is here to help.
|
50
52
|
|
51
|
-
|
53
|
+
## Installation
|
52
54
|
|
53
55
|
*Rails 3.x*
|
54
56
|
|
55
57
|
To use it, add it to your Gemfile:
|
56
58
|
|
57
|
-
|
59
|
+
`gem 'has-many-with-set'`
|
58
60
|
|
59
61
|
That's pretty much it!
|
60
62
|
|
61
|
-
|
63
|
+
## Usage
|
62
64
|
|
63
65
|
To to use *_has-many-with-set_* to relate two already existing models you have to create the underlying tables that are going to be used by it, this is very easily done by generating a migration for them:
|
64
66
|
|
65
|
-
|
67
|
+
`rails generate has_many_with_set:migration PARENT CHILD`
|
66
68
|
|
67
69
|
And add the relationship to your parent model:
|
68
70
|
|
69
|
-
|
71
|
+
```
|
72
|
+
class Parent < ActiveRecord::Base
|
70
73
|
has_many_with_set :children
|
71
74
|
end
|
75
|
+
```
|
72
76
|
|
73
|
-
|
77
|
+
And that's it! You can start using it in your application. This can be done for as many models as you want, (you have to create migrations for all combinations!) you can even use multiple sets to relate different data to the same parent model (like Authors and Tags for your Articles).
|
74
78
|
|
75
|
-
|
79
|
+
## Example
|
76
80
|
|
77
81
|
Using our previous example:
|
78
82
|
|
79
|
-
|
83
|
+
```
|
84
|
+
rails g model Article title:string body:text`
|
80
85
|
|
81
|
-
|
86
|
+
rails g model Tag name:string
|
82
87
|
|
83
|
-
|
88
|
+
rails g has_many_with_set:migration Article Tag
|
84
89
|
create db/migrate/20121106063326_create_articles_tags_set.rb
|
85
90
|
|
86
|
-
|
91
|
+
class Article < ApplicationRecord
|
87
92
|
has_many_with_set :tags # <--- key part!
|
88
93
|
end
|
89
94
|
|
@@ -123,13 +128,13 @@ Tag.first.articles.size
|
|
123
128
|
Tag.first.articles.first
|
124
129
|
=> #<Article id: 2, title: "Buzzword about buzzwords!", ..>
|
125
130
|
|
126
|
-
|
131
|
+
```
|
127
132
|
|
128
|
-
|
133
|
+
Same example as before, just now using *_has_many_with_set_*. We get the impressive number of 80 rows to represent the same information that we had before with thousands of rows (roughly the same, since we use random combinations is not _exactly_ the same article/tag layout).
|
129
134
|
|
130
|
-
|
135
|
+
The funny thing in this particular example, is that since we have only five tags, there are only 32 possible ways to combine five tags together, these 32 combinations amount to 80 rows in our relationship table.... that is, even if we had a million articles we would still have the same 80 rows to represent our relationships, we don't need to create any more rows!!
|
131
136
|
|
132
|
-
|
137
|
+
## Final remarks
|
133
138
|
|
134
139
|
Please keep in mind that *_has-many-with-set_* is not without some caveats:
|
135
140
|
|
@@ -139,7 +144,7 @@ Please keep in mind that *_has-many-with-set_* is not without some caveats:
|
|
139
144
|
|
140
145
|
This is one humble attempt to help make Ruby On Rails a bit more useful with large data sets and applications, I hope you enjoy it and is useful to you, please email me with comments or suggestions (or even code!).
|
141
146
|
|
142
|
-
|
147
|
+
## Author
|
143
148
|
|
144
149
|
* Francisco Soto <ebobby@ebobby.org>
|
145
150
|
|
@@ -1,31 +1,32 @@
|
|
1
1
|
module HasManyWithSet
|
2
2
|
module Accessors
|
3
|
-
def self.build_loader_method
|
4
|
-
set_table_id = "#{ set_table_name.singularize }_id"
|
5
|
-
set_table_name_singular = set_table_name.singularize
|
3
|
+
def self.build_loader_method(child_table_name, set_table_name)
|
4
|
+
set_table_id = "#{ set_table_name.singularize }_id".to_sym
|
5
|
+
set_table_name_singular = set_table_name.singularize.to_sym
|
6
6
|
|
7
|
-
Proc.new
|
7
|
+
Proc.new do
|
8
8
|
values = []
|
9
|
-
|
9
|
+
|
10
|
+
values = send(set_table_name_singular).send(child_table_name).to_a unless
|
11
|
+
send(set_table_id).nil?
|
12
|
+
|
10
13
|
values
|
11
|
-
|
14
|
+
end
|
12
15
|
end
|
13
16
|
|
14
|
-
def self.build_getter_method
|
15
|
-
Proc.new
|
16
|
-
|
17
|
-
|
18
|
-
unless values
|
19
|
-
values = send(loader_method_name)
|
17
|
+
def self.build_getter_method(instance_var_name, loader_method_name)
|
18
|
+
Proc.new do
|
19
|
+
unless instance_variable_defined?(instance_var_name)
|
20
|
+
values = send(loader_method_name.to_sym)
|
20
21
|
instance_variable_set(instance_var_name, values)
|
21
22
|
end
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
instance_variable_get(instance_var_name)
|
25
|
+
end
|
25
26
|
end
|
26
27
|
|
27
|
-
def self.build_setter_method
|
28
|
-
Proc.new
|
28
|
+
def self.build_setter_method(instance_var_name)
|
29
|
+
Proc.new do |elements|
|
29
30
|
elements = [] if elements.nil?
|
30
31
|
|
31
32
|
unless elements.is_a? Array
|
@@ -39,10 +40,10 @@ module HasManyWithSet
|
|
39
40
|
elements = elements.flatten.uniq
|
40
41
|
|
41
42
|
instance_variable_set(instance_var_name, elements)
|
42
|
-
|
43
|
+
end
|
43
44
|
end
|
44
45
|
|
45
|
-
def self.build_parent_loader_method
|
46
|
+
def self.build_parent_loader_method(parent_table_name, child_table_name, set_table_name, set_items_table_name)
|
46
47
|
find_query = Queries.build_find_parents_query(parent_table_name, child_table_name, set_table_name, set_items_table_name)
|
47
48
|
|
48
49
|
parent_klass = Object.const_get(parent_table_name.classify)
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module HasManyWithSet
|
2
2
|
module Callbacks
|
3
|
-
def self.build_saver_callback
|
4
|
-
|
3
|
+
def self.build_saver_callback(set_table_name, set_items_table_name,
|
4
|
+
child_table_name, instance_var_name)
|
5
5
|
empty_set_query = Queries.build_find_empty_set_query(set_table_name, set_items_table_name)
|
6
6
|
find_set_query = Queries.build_find_set_query(set_table_name, set_items_table_name, child_table_name)
|
7
7
|
|
8
|
-
set_item_id_setter = "#{ set_table_name.singularize }_id="
|
9
|
-
set_items_setter = "#{ child_table_name }="
|
8
|
+
set_item_id_setter = "#{ set_table_name.singularize }_id=".to_sym
|
9
|
+
set_items_setter = "#{ child_table_name }=".to_sym
|
10
10
|
|
11
11
|
klass = Object.const_get(set_table_name.classify)
|
12
12
|
|
13
|
-
Proc.new
|
13
|
+
Proc.new do
|
14
14
|
set = nil
|
15
15
|
values = send(child_table_name)
|
16
16
|
|
@@ -44,7 +44,7 @@ module HasManyWithSet
|
|
44
44
|
end
|
45
45
|
|
46
46
|
send(set_item_id_setter, set.id)
|
47
|
-
|
47
|
+
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module HasManyWithSet
|
2
2
|
# This is the magic entry point method that adds set relationships to a model.
|
3
|
-
def has_many_with_set
|
3
|
+
def has_many_with_set(child)
|
4
4
|
build_set_relationship self.to_s, child.to_s.classify
|
5
5
|
end
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
def build_set_relationship
|
9
|
+
def build_set_relationship(parent_model_name, child_model_name)
|
10
10
|
parent_table_name = parent_model_name.tableize
|
11
11
|
child_table_name = child_model_name.tableize
|
12
12
|
set_table_name = "#{ parent_table_name }_#{ child_table_name }_sets"
|
@@ -52,7 +52,7 @@ module HasManyWithSet
|
|
52
52
|
private loader_method_name
|
53
53
|
private save_callback_method_name
|
54
54
|
|
55
|
-
before_save save_callback_method_name
|
55
|
+
before_save save_callback_method_name.to_sym
|
56
56
|
end
|
57
57
|
end
|
58
58
|
end
|
@@ -19,7 +19,7 @@ module HasManyWithSet
|
|
19
19
|
having count(*) = ?;"
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.build_find_parents_query
|
22
|
+
def self.build_find_parents_query(parent_table_name, child_table_name, set_table_name, set_items_table_name)
|
23
23
|
"select #{ parent_table_name }.* from #{ child_table_name }
|
24
24
|
join #{ set_items_table_name } on #{ child_table_name }.id = #{ set_items_table_name }.#{ child_table_name.singularize }_id
|
25
25
|
join #{ parent_table_name } on #{ parent_table_name }.#{ set_table_name.singularize }_id =
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module HasManyWithSet
|
2
2
|
module Relationships
|
3
|
-
def self.create_set_model
|
4
|
-
Object.const_set(set_model_name, Class.new(
|
3
|
+
def self.create_set_model(set_model_name)
|
4
|
+
Object.const_set(set_model_name, Class.new(ApplicationRecord)) unless
|
5
5
|
Object.const_defined?(set_model_name) # this *should* never happen...
|
6
6
|
end
|
7
7
|
|
8
|
-
def self.relate_child_to_set
|
8
|
+
def self.relate_child_to_set(set_model_name, child_model_name)
|
9
9
|
# Take the child model and add a regular many-to-many relationship to the Set model...
|
10
10
|
Object.const_get(child_model_name).class_eval do
|
11
11
|
has_and_belongs_to_many set_model_name.tableize.to_sym, :join_table => "#{ set_model_name.tableize }_#{ child_model_name.tableize }"
|
@@ -17,10 +17,10 @@ module HasManyWithSet
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def self.relate_parent_to_set
|
20
|
+
def self.relate_parent_to_set(set_model_name, parent_model_name)
|
21
21
|
# The parent object has a FK to the Set table, so it belongs_to it.
|
22
22
|
Object.const_get(parent_model_name).class_eval do
|
23
|
-
belongs_to set_model_name.tableize.singularize.to_sym
|
23
|
+
belongs_to set_model_name.tableize.singularize.to_sym, optional: true
|
24
24
|
end
|
25
25
|
end
|
26
26
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require "test_helper"
|
2
2
|
|
3
|
-
PARENT = "
|
4
|
-
CHILD = "
|
3
|
+
PARENT = "One"
|
4
|
+
CHILD = "Two"
|
5
5
|
MIGRATION_PATH = "test/tmp/"
|
6
|
-
MIGRATION_FILE = "db/migrate/
|
6
|
+
MIGRATION_FILE = "db/migrate/create_ones_twos_set"
|
7
7
|
|
8
8
|
PrepareActiveRecord.prepare_default_schema
|
9
9
|
|
@@ -20,127 +20,120 @@ class MigrationGeneratorTest < Rails::Generators::TestCase
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
PrepareActiveRecord.run_migration(MIGRATION_FILE, MIGRATION_PATH)
|
24
|
-
|
25
23
|
class HasManyWithSetTest < ActiveSupport::TestCase
|
26
24
|
def setup
|
27
|
-
|
28
|
-
|
29
|
-
# test the whole thing.
|
30
|
-
PrepareActiveRecord.prepare_default_schema
|
31
|
-
PrepareActiveRecord.run_migration(MIGRATION_FILE, MIGRATION_PATH)
|
32
|
-
@initialized = true
|
33
|
-
end
|
25
|
+
PrepareActiveRecord.prepare_default_schema
|
26
|
+
PrepareActiveRecord.run_migration(PARENT, CHILD)
|
34
27
|
end
|
35
28
|
|
36
29
|
test "parent class has the getter" do
|
37
|
-
assert_respond_to
|
30
|
+
assert_respond_to One.new, "twos"
|
38
31
|
end
|
39
32
|
|
40
33
|
test "parent class has the setter" do
|
41
|
-
assert_respond_to
|
34
|
+
assert_respond_to One.new, "twos="
|
42
35
|
end
|
43
36
|
|
44
37
|
test "child class has the getter" do
|
45
|
-
assert_respond_to
|
38
|
+
assert_respond_to Two.new, "ones"
|
46
39
|
end
|
47
40
|
|
48
41
|
test "getter type" do
|
49
|
-
assert_kind_of Array,
|
42
|
+
assert_kind_of Array, One.new.twos
|
50
43
|
end
|
51
44
|
|
52
45
|
test "children can be saved" do
|
53
46
|
15.times do
|
54
|
-
assert
|
47
|
+
assert Two.new.save
|
55
48
|
end
|
56
49
|
|
57
|
-
assert (
|
50
|
+
assert (Two.all.size == 15)
|
58
51
|
end
|
59
52
|
|
60
53
|
test "parent saved with empty set" do
|
61
|
-
assert
|
62
|
-
assert
|
54
|
+
assert One.new(:num => 0).save
|
55
|
+
assert One.last.twos.size == 0
|
63
56
|
end
|
64
57
|
|
65
58
|
test "parent saved with non-empty set" do
|
66
|
-
record =
|
67
|
-
record.
|
68
|
-
record.num = record.
|
59
|
+
record = One.new
|
60
|
+
record.twos = Two.all
|
61
|
+
record.num = record.twos.size
|
69
62
|
assert record.save
|
70
63
|
|
71
|
-
record =
|
72
|
-
assert record.num == record.
|
64
|
+
record = One.find(record.id)
|
65
|
+
assert record.num == record.twos.size
|
73
66
|
end
|
74
67
|
|
75
68
|
test "parent saved with several children" do
|
76
|
-
|
77
|
-
record =
|
78
|
-
record.
|
69
|
+
Two.all.each do |m|
|
70
|
+
record = One.new(:num => 1)
|
71
|
+
record.twos << m
|
79
72
|
assert record.save
|
80
73
|
|
81
|
-
record =
|
82
|
-
assert record.num == record.
|
74
|
+
record = One.find(record.id)
|
75
|
+
assert record.num == record.twos.size
|
83
76
|
end
|
84
77
|
end
|
85
78
|
|
86
79
|
test "set reuse" do
|
87
|
-
items =
|
80
|
+
items = Two.all
|
88
81
|
|
89
82
|
25.times do
|
90
|
-
master_record =
|
83
|
+
master_record = One.new
|
91
84
|
|
92
85
|
rand(items.size + 1).times do
|
93
|
-
master_record.
|
86
|
+
master_record.twos << items[rand(items.size)]
|
94
87
|
end
|
95
88
|
|
96
|
-
master_record.num = master_record.
|
89
|
+
master_record.num = master_record.twos.size
|
97
90
|
master_record.save
|
98
91
|
|
99
|
-
master_items = master_record.
|
92
|
+
master_items = master_record.twos
|
100
93
|
|
101
|
-
set_id = master_record.send(
|
94
|
+
set_id = master_record.send(:ones_twos_set_id)
|
102
95
|
|
103
96
|
100.times do
|
104
|
-
record =
|
105
|
-
record.
|
97
|
+
record = One.new(:num => master_items.size)
|
98
|
+
record.twos = master_items
|
106
99
|
record.save
|
107
100
|
|
108
|
-
assert(record.send(
|
109
|
-
"Set ids do not match #{ record.send(
|
101
|
+
assert(record.send(:ones_twos_set_id) == set_id,
|
102
|
+
"Set ids do not match #{ record.send(:ones_twos_set_id) } == #{ set_id }")
|
110
103
|
end
|
111
104
|
end
|
112
105
|
end
|
113
106
|
|
114
107
|
test "do not save repeated items" do
|
115
|
-
items =
|
116
|
-
master_record =
|
108
|
+
items = Two.all
|
109
|
+
master_record = One.new(:num => items.size)
|
117
110
|
|
118
|
-
master_record.
|
119
|
-
master_record.
|
120
|
-
master_record.
|
121
|
-
master_record.
|
111
|
+
master_record.twos = Two.all
|
112
|
+
master_record.twos << items
|
113
|
+
master_record.twos << items
|
114
|
+
master_record.twos << items
|
122
115
|
master_record.save
|
123
116
|
|
124
|
-
assert master_record.
|
117
|
+
assert master_record.twos.size == items.size
|
125
118
|
end
|
126
119
|
|
127
120
|
test "children can see parents" do
|
128
|
-
item =
|
121
|
+
item = Two.create
|
129
122
|
|
130
123
|
how_many = rand(50)
|
131
124
|
|
132
125
|
how_many.times do
|
133
|
-
record =
|
134
|
-
record.
|
126
|
+
record = One.new(:num => 1)
|
127
|
+
record.twos << item
|
135
128
|
record.save
|
136
129
|
end
|
137
130
|
|
138
|
-
assert item.
|
131
|
+
assert item.ones.size == how_many, "#{ item.ones.size } != #{ how_many }"
|
139
132
|
end
|
140
133
|
|
141
134
|
test "items count match" do
|
142
|
-
|
143
|
-
assert m.num == m.
|
135
|
+
One.all.each do |m|
|
136
|
+
assert m.num == m.twos.size
|
144
137
|
end
|
145
138
|
end
|
146
139
|
end
|
data/test/support/models.rb
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
class
|
1
|
+
class ApplicationRecord < ActiveRecord::Base
|
2
|
+
self.abstract_class = true
|
2
3
|
end
|
3
4
|
|
4
|
-
class
|
5
|
-
|
5
|
+
class Two < ApplicationRecord
|
6
|
+
end
|
7
|
+
|
8
|
+
class One < ApplicationRecord
|
9
|
+
has_many_with_set :two
|
6
10
|
end
|
@@ -6,29 +6,29 @@ class PrepareActiveRecord
|
|
6
6
|
ActiveRecord::Schema.define do
|
7
7
|
self.verbose = false
|
8
8
|
|
9
|
-
create_table :
|
9
|
+
create_table :ones do |t|
|
10
10
|
t.integer :num
|
11
11
|
t.timestamps
|
12
12
|
end
|
13
13
|
|
14
|
-
create_table :
|
14
|
+
create_table :twos do |t|
|
15
15
|
t.timestamps
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
def run_migration(
|
21
|
-
|
20
|
+
def run_migration(parent, child)
|
21
|
+
generator = HasManyWithSet::MigrationGenerator.new([parent, child])
|
22
|
+
generator.destination_root = Dir.tmpdir
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
migration_path = generator.create_migration_file
|
25
|
+
migration_file = File.join(Dir.tmpdir, migration_path)
|
26
|
+
|
27
|
+
require(migration_file)
|
25
28
|
|
26
|
-
|
29
|
+
CreateOnesTwosSet.new.change
|
27
30
|
|
28
|
-
|
29
|
-
absolute = File.expand_path(relative, root)
|
30
|
-
dirname, file_name = File.dirname(absolute), File.basename(absolute).sub(/\.rb$/, '')
|
31
|
-
Dir.glob("#{dirname}/[0-9]*_*.rb").grep(/\d+_#{file_name}.rb$/).first
|
31
|
+
File.delete(migration_file)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateOnesTwosSet < ActiveRecord::Migration[5.0]
|
2
|
+
def change
|
3
|
+
create_table :ones_twos_sets do |t|
|
4
|
+
t.timestamps
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table :ones_twos_sets_twos do |t|
|
8
|
+
t.references :ones_twos_set, :null => false
|
9
|
+
t.references :two, :null => false
|
10
|
+
end
|
11
|
+
|
12
|
+
add_column :ones, :ones_twos_set_id, :integer
|
13
|
+
|
14
|
+
add_index :ones, :ones_twos_set_id
|
15
|
+
add_index :ones_twos_sets_twos, :ones_twos_set_id, :name => :ix_items_ones_twos_sets_twos
|
16
|
+
add_index :ones_twos_sets_twos, :two_id, :name => :ix_twos_ones_twos_sets_twos
|
17
|
+
end
|
18
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: has-many-with-set
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francisco Soto
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: sqlite3
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -47,7 +47,7 @@ extra_rdoc_files: []
|
|
47
47
|
files:
|
48
48
|
- CHANGELOG
|
49
49
|
- MIT-LICENSE
|
50
|
-
- README.
|
50
|
+
- README.md
|
51
51
|
- Rakefile
|
52
52
|
- lib/generators/has_many_with_set/migration_generator.rb
|
53
53
|
- lib/generators/has_many_with_set/templates/sets.rb.erb
|
@@ -62,7 +62,7 @@ files:
|
|
62
62
|
- test/support/models.rb
|
63
63
|
- test/support/prepare_activerecord.rb
|
64
64
|
- test/test_helper.rb
|
65
|
-
- test/tmp/db/migrate/
|
65
|
+
- test/tmp/db/migrate/20180923002305_create_ones_twos_set.rb
|
66
66
|
homepage: https://github.com/ebobby/has-many-with-set
|
67
67
|
licenses: []
|
68
68
|
metadata: {}
|
@@ -82,13 +82,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
82
|
version: '0'
|
83
83
|
requirements: []
|
84
84
|
rubyforge_project:
|
85
|
-
rubygems_version: 2.
|
85
|
+
rubygems_version: 2.7.6
|
86
86
|
signing_key:
|
87
87
|
specification_version: 4
|
88
88
|
summary: A smarter way of doing many-to-many relationships in Rails.
|
89
89
|
test_files:
|
90
|
+
- test/tmp/db/migrate/20180923002305_create_ones_twos_set.rb
|
90
91
|
- test/has-many-with-set_test.rb
|
91
|
-
- test/support/models.rb
|
92
92
|
- test/support/prepare_activerecord.rb
|
93
|
+
- test/support/models.rb
|
93
94
|
- test/test_helper.rb
|
94
|
-
- test/tmp/db/migrate/20141013205312_create_model_ones_model_twos_set.rb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
class CreateModelOnesModelTwosSet < ActiveRecord::Migration
|
2
|
-
def change
|
3
|
-
create_table :model_ones_model_twos_sets do |t|
|
4
|
-
t.timestamps
|
5
|
-
end
|
6
|
-
|
7
|
-
create_table :model_ones_model_twos_sets_model_twos do |t|
|
8
|
-
t.references :model_ones_model_twos_set, :null => false
|
9
|
-
t.references :model_two, :null => false
|
10
|
-
end
|
11
|
-
|
12
|
-
add_column :model_ones, :model_ones_model_twos_set_id, :integer
|
13
|
-
|
14
|
-
add_index :model_ones, :model_ones_model_twos_set_id
|
15
|
-
add_index :model_ones_model_twos_sets_model_twos, :model_ones_model_twos_set_id, :name => :ix_items_model_ones_model_twos_sets_model_twos
|
16
|
-
add_index :model_ones_model_twos_sets_model_twos, :model_two_id, :name => :ix_model_twos_model_ones_model_twos_sets_model_twos
|
17
|
-
end
|
18
|
-
end
|