acts_has_many 0.3.0 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 899f42f7868ed45b0eb22bdd0e56d3cf4a2385af
4
+ data.tar.gz: 95a0effdaf788f947e92fabea3dec9e7a51e219d
5
+ SHA512:
6
+ metadata.gz: 724009b91d5dee328d7eca99829c8212a31a778f29132cad80aa0f6aebbf4bb3e501e204213faffdcf7cd05ffd12658ee94345d8c60bf1debc24b597dbd29436
7
+ data.tar.gz: bb297b2056cd2f77a74ef544daf0bea950fd4781a3b49b92cc27b858812f15728ff303d251b98fd4e07a4d1763a4874f851687689fda06e3a82aee2d2e4cfd5b
data/README.md CHANGED
@@ -12,7 +12,7 @@ Add this line to your application's Gemfile:
12
12
 
13
13
  And then execute:
14
14
 
15
- $ bundle
15
+ $ bundle install
16
16
 
17
17
  Or install it yourself as:
18
18
 
@@ -25,54 +25,74 @@ Or install it yourself as:
25
25
 
26
26
  4. If only `acts_has_many` is used:
27
27
  ```ruby
28
- class User < ActiveRecord::Base
29
- belongs_to :company, dependent: :destroy
28
+ class Posting < ActiveRecord::Base
29
+ belongs_to :tag, dependent: :destroy
30
30
  end
31
31
 
32
- class Company < ActiveRecord::Base
33
- has_many :users
32
+ class Tag < ActiveRecord::Base
33
+ has_many :postings
34
34
 
35
- acts_has_many :users
35
+ acts_has_many :postings
36
36
  end
37
37
  ```
38
38
  In this case you have `has_many_update` method:
39
39
  ```ruby
40
- Company.first.has_many_update {title: 'Google'}
40
+ new_record, delete_record = Tag.first.has_many_update {title: 'ruby'}
41
41
  ```
42
- if you use `acts_has_many` with `through: true` paramters:
42
+ if you use `acts_has_many` with `through: true` parameters:
43
43
  ```ruby
44
- new_records, delete_ids = Company.has_many_through_update(update: data, new: date)
44
+ new_records, delete_ids = Tag.has_many_through_update(update: data, new: date)
45
45
  ```
46
46
 
47
47
  5. If you use `acts_has_many` with `acts_has_many_for`
48
48
  ```ruby
49
- class User < ActiveRecord::Base
50
- belongs_to :company, dependent: :destroy
49
+ class Posting < ActiveRecord::Base
50
+ belongs_to :tag, dependent: :destroy
51
51
 
52
- acts_has_many_for :company
52
+ acts_has_many_for :tag
53
53
  end
54
54
 
55
- class Company < ActiveRecord::Base
56
- has_many :users
55
+ class Tag < ActiveRecord::Base
56
+ has_many :postings
57
57
 
58
- acts_has_many :users
58
+ acts_has_many :postings
59
59
  end
60
60
  ```
61
61
  In this case you can use the same that is in 4-th point and also:
62
62
  ```ruby
63
- User.first.company_attributes = {title: 'Google'}
63
+ Posting.first.tag_attributes = {title: 'ruby'}
64
64
  ```
65
- if you use `acts_has_many` with `through: true` paramters
65
+ if you use `acts_has_many` with `through: true` parameters
66
66
  ```ruby
67
- User.first.companies_collection = [{title: 'Google'}, {title: 'Apple'}]
67
+ Posting.first.tags_collection = [{title: 'ruby'}, {title: 'python'}]
68
68
  ```
69
69
 
70
+ New in v0.3.2
71
+ --------------
72
+ Use `block` to change condition, default search is `where :compare => :value`
73
+ ```ruby
74
+ class Tag < ActiveRecord::Base
75
+ has_many :postings
76
+
77
+ acts_has_many :postings do |params|
78
+ where arel_table[:title].matches(params[:title])
79
+ end
80
+ end
81
+ ```
82
+ Replace `compare` method to `condition`
83
+
84
+ Notice, if block is defined:
85
+ >* `:compare` argument will be ignored
86
+ >* auto `validates :compare, uniqueness: true` is off
87
+
88
+
70
89
  More
71
90
  ----
72
91
  `acts_has_many` options:
73
92
  >* list relations or after necessary relations
74
93
  >* :compare( string or symbol; default: :title) - name column with unique elements in table
75
94
  >* :through( boolean; default: false) - if you use has_many :through
95
+ >* &block(should return ActiveRecord::Relation; default: `where compare: params[:compare]`) - change condition
76
96
 
77
97
  `acts_has_many_for` options:
78
98
  >* list necessary relations
@@ -90,13 +110,99 @@ More
90
110
  `<relation>_collection` options:
91
111
  >* data - Array (Records, Hash, Empty)
92
112
 
93
- additionl
113
+ Additional
94
114
  >* `depend_relations` - show depend relations(Array)
95
115
  >* `actual?` - check actuality(Boolean)
96
- >* `compare` - return compare column(String)
116
+ >* `condition` - call block(in: params, out: ActiveRecord::Relation)
97
117
  >* `destroy!` - standart destroy
98
118
  >* `destroy` - destroy with cheking actuality record
99
119
 
120
+ Examples
121
+ --------
122
+ Use with `has_manay`:
123
+ ```ruby
124
+ class Posting < ActiveRecord::Base
125
+ belongs_to :tag, dependent: :destroy
126
+
127
+ acts_has_many_for :tag
128
+ end
129
+
130
+ class Tag < ActiveRecord::Base
131
+ has_many :postings
132
+
133
+ acts_has_many :postings, compare: :name
134
+ end
135
+
136
+ posting = Posting.create title: 'First posting',
137
+ tag_attributes: {name: 'ruby'}
138
+
139
+ posting.tag # => #<Tag id: 1, title: "ruby">
140
+ Tag.all # => [#<Tag id: 1, title: "ruby">]
141
+
142
+ posting = Posting.create title: 'Second posting',
143
+ tag_attributes: {name: 'ruby'}
144
+
145
+ posting.tag # => #<Tag id: 1, title: "ruby">
146
+ Tag.all # => [#<Tag id: 1, title: "ruby">]
147
+
148
+ posting.update_attributes tag_attributes: {name: 'python'}
149
+
150
+ posting.tag # => #<Tag id: 2, title: "python">
151
+ Tag.all # => [#<Tag id: 1, title: "ruby">, #<Tag id: 2, title: "python">]
152
+
153
+ posting.tag_attributes = Tag.first
154
+ posting.save
155
+
156
+ Tag.all # => [#<Tag id: 1, title: "ruby">]
157
+ ```
158
+ Use with `has_many :through`
159
+ ```ruby
160
+ class Posting < ActiveRecord::Base
161
+ has_many :posting_tags, dependent: :destroy
162
+ has_many :tags, through: :posting_tags
163
+
164
+ acts_has_many_for :tags
165
+ end
166
+
167
+ class PostingTag < ActiveRecord::Base
168
+ belongs_to :posting
169
+ belongs_to :tag
170
+ end
171
+
172
+ class Tag < ActiveRecord::Base
173
+ has_many :postings, through: :posting_tags
174
+ has_many :posting_tags
175
+
176
+ acts_has_many :postings, through: true
177
+ end
178
+
179
+ posting = Posting.create title: 'First posting',
180
+ tags_collection: [{name: 'ruby'}, {name: 'python'}]
181
+
182
+ posting.tags
183
+ # => [#<Tag id: 1, title: "ruby">, #<Tag id: 2, title: "python">]
184
+ Tag.all
185
+ # => [#<Tag id: 1, title: "ruby">, #<Tag id: 2, title: "python">]
186
+
187
+ posting = Posting.create title: 'Second posting',
188
+ tags_collection: [{name: 'ruby'}, {name: 'java'}]
189
+
190
+ posting.tags
191
+ # => [#<Tag id: 1, title: "ruby">, #<Tag id: 3, title: "java">]
192
+ Tag.all
193
+ # => [#<Tag id: 1, title: "ruby">, #<Tag id: 2, title: "python">, #<Tag id: 3, title: "java">]
194
+
195
+ posting.update_attributes tags_collection: [Tag.first]
196
+
197
+ posting.tags # => [#<Tag id: 2, title: "ruby">]
198
+ Tag.all
199
+ # => [#<Tag id: 1, title: "ruby">, #<Tag id: 2, title: "python">]
200
+
201
+ Posting.first.destroy
202
+
203
+ Tag.all # => [#<Tag id: 1, title: "ruby">]
204
+ ```
205
+
100
206
  Contributing
101
207
  ------------
102
208
  You can help improve this project.
@@ -107,7 +213,7 @@ Here are some ways *you* can contribute:
107
213
  * by suggesting new features
108
214
  * by writing or editing documentation
109
215
  * by writing specifications
110
- * by writing code (**no patch is too small**: fix typos, add comments, clean up inconsistent whitespace)
216
+ * by writing code
111
217
  * by refactoring code
112
218
  * by closing [issues](https://github.com/igor04/acts_has_many/issues)
113
219
  * by reviewing patches
@@ -1,40 +1,32 @@
1
1
  module ActiveRecord
2
2
  module ActsHasMany
3
-
4
- # Class methods:
5
- # <tt>has_many_through_update</tt>
6
- #
7
- # Instance methods:
8
- # <tt>has_many_update</tt>
9
- # <tt>actual?</tt>
10
- # <tt>destroy</tt>
11
- # <tt>destroy!</tt>
12
3
  module Child
13
-
14
- # <tt>has_many_update</tt> (return: array) - [new_record, delete_record]
15
- # options: data (type: hash) - data for updte
16
4
  def has_many_update data
17
- data = { model.compare => ''}.merge data
5
+ current = self
6
+ condition = current.class.condition(data.symbolize_keys)
18
7
 
19
- has_many_cleaner data.symbolize_keys
8
+ if actual? || current.new_record?
9
+ [condition.first_or_create(data), nil]
10
+ elsif exists = condition.first
11
+ [exists, (current == exists ? nil : current)]
12
+ else
13
+ update_attributes data
14
+ [current, nil]
15
+ end
20
16
  end
21
17
 
22
- # destroy with check actuality
23
18
  def destroy
24
19
  return false if actual? false
25
20
  super
26
21
  end
27
22
 
28
- # original destroy
29
23
  def destroy!
30
24
  self.class.superclass.instance_method(:destroy).bind(self).call
31
25
  end
32
26
 
33
- # <tt>actual?</tt> - check the acutuality of element in has_many table
34
- # options: exclude (boolean, default: true) - ignore one record or no
35
27
  def actual? exclude = true
36
28
  actual = 0
37
- model.dependent_relations.each do |dependent_relation|
29
+ self.class.dependent_relations.each do |dependent_relation|
38
30
  tmp = self.send dependent_relation
39
31
  actual += tmp.all.size
40
32
  end
@@ -43,46 +35,7 @@ module ActiveRecord
43
35
  end
44
36
  end
45
37
 
46
- private
47
-
48
- # <tt>has_many_cleaner</tt> - base mothod
49
- def has_many_cleaner data
50
- compare = { model.compare => data[model.compare] }
51
-
52
- new_record = self
53
- del_record = nil
54
-
55
- if actual?
56
- new_record = model.where(compare).first_or_create data
57
- else
58
- object_tmp = model.where(compare).first
59
- if object_tmp.nil?
60
- if new_record.id.nil?
61
- new_record = model.where(compare).first_or_create data
62
- else
63
- if data[model.compare].blank?
64
- del_record, new_record = new_record, nil
65
- else
66
- update_attributes data
67
- end
68
- end
69
- else
70
- del_record = (new_record.id == object_tmp.id) ? nil : new_record
71
- new_record = object_tmp
72
- end
73
- end
74
- [new_record, del_record]
75
- end
76
-
77
-
78
38
  module ChildThrough
79
-
80
- # <tt>has_many_through_update</tt> (return array) [ 1 - array new records, 2 - array delete records ]
81
- # options
82
- # :update (array) - data for update (id and data)
83
- # :new (array) - data for create record (data)
84
- #
85
- # +for delete records need use method destroy !!!+
86
39
  def has_many_through_update(options)
87
40
  record_add = []
88
41
  record_del = []
@@ -96,8 +49,7 @@ module ActiveRecord
96
49
  unless options[:new].nil?
97
50
  options[:new].uniq!
98
51
  options[:new].each do |data|
99
- data = data.symbolize_keys
100
- record_add << where(compare => data[compare]).first_or_create(data)
52
+ record_add << new.has_many_update(data).first
101
53
  record_del.delete record_add.last
102
54
  end
103
55
  end
@@ -1,32 +1,17 @@
1
1
  module ActiveRecord
2
2
  module ActsHasMany
3
-
4
- # Class methods:
5
- # <tt><relation>_attributes=</tt>
6
- # <tt><relation>_collection=</tt>
7
3
  module Parent
4
+ extend ActiveSupport::Concern
8
5
 
9
- def self.included base
10
-
11
- # Generate class methods
12
- # <tt><relation>_attributes=</tt> - set one element (use with belogns_to)
13
- # options: data (type: Hash, existing recod, NilClass)
14
- #
15
- # Create or update child record and set to parent when `data` is Hash
16
- # Change data with delating or leaving child record when `data` is exists record, or NilClass
17
- #
18
- # <tt><relation>_collection=</tt> - set many elements (use with has_many :through)
19
- # options: data (type: Array with (exist records or Hash)
20
- #
21
- # Create or select exists records and set to parent, unused record try destory
22
- base.dependent_relations.each do |relation|
23
- unless base.reflect_on_association relation.to_sym
6
+ included do
7
+ dependent_relations.each do |relation|
8
+ unless reflect_on_association relation.to_sym
24
9
  raise ArgumentError, "No association found for name `#{relation}`. Has it been defined yet?"
25
10
  end
26
11
 
27
12
  relation = relation.to_s
28
- unless base.reflect_on_association(relation.to_sym).collection?
29
- base.class_eval <<-EOV, __FILE__ , __LINE__ + 1
13
+ unless reflect_on_association(relation.to_sym).collection?
14
+ class_eval <<-EOV, __FILE__ , __LINE__ + 1
30
15
  def #{relation}_attributes= data
31
16
  self.tmp_garbage ||= {}
32
17
  current = self.#{relation}
@@ -47,7 +32,7 @@ module ActiveRecord
47
32
  end
48
33
  EOV
49
34
  else
50
- base.class_eval <<-EOV, __FILE__ , __LINE__ + 1
35
+ class_eval <<-EOV, __FILE__ , __LINE__ + 1
51
36
  def #{relation}_collection= data
52
37
  self.tmp_garbage ||= {}
53
38
 
@@ -76,7 +61,6 @@ module ActiveRecord
76
61
 
77
62
  private
78
63
 
79
- # <tt>clear_garbage</tt> work with after_save and try destroied records from tmp_garbage
80
64
  def clear_garbage
81
65
  self.tmp_garbage.each do |relation, record|
82
66
  if record.is_a? Array
@@ -1,33 +1,17 @@
1
1
  module ActiveRecord
2
2
  module ActsHasMany
3
-
4
- # Class methods: (for use in your model)
5
- # <tt>acts_has_many_for</tt>
6
- # <tt>acts_has_many</tt>
7
- def self.included base
8
- base.extend ClassMethods
9
- end
3
+ extend ActiveSupport::Concern
10
4
 
11
5
  module ClassMethods
12
-
13
- # Class methods:
14
- # <tt>dependent_relations</tt>
15
- # <tt>compare</tt>
16
- # <tt>model</tt>
17
- # <tt>has_many_through_update</tt>
18
- # Instance mothods:
19
- # <tt>actual?</tt>
20
- # <tt>has_many_update</tt>
21
- # Set:
22
- # validates for <compare_element> (uniqueness: true, presence: true)
23
- def acts_has_many *opt
24
- options = { compare: :title, through: false }
6
+ def acts_has_many *opt, &block
7
+ options = {compare: :title, through: false}
25
8
  options.update opt.extract_options!
26
9
  options.assert_valid_keys :compare, :through
27
- options[:relations] = opt
28
10
 
29
- options[:relations] = self.reflect_on_all_associations(:has_many)
30
- .map(&:name) if options[:relations].blank?
11
+ options[:relations] = opt
12
+ if options[:relations].blank?
13
+ options[:relations] = self.reflect_on_all_associations(:has_many).map(&:name)
14
+ end
31
15
 
32
16
  dependent_relations = []
33
17
  options[:relations].each do |relation|
@@ -38,33 +22,26 @@ module ActiveRecord
38
22
  end
39
23
  end
40
24
 
25
+ if block_given?
26
+ self.class.send :define_method, :condition, block
27
+ else
28
+ self.class.send :define_method, :condition do |data|
29
+ where options[:compare] => data[options[:compare]]
30
+ end
31
+ end
32
+
41
33
  class_eval <<-EOV, __FILE__ , __LINE__ + 1
42
34
  def self.dependent_relations
43
35
  #{dependent_relations}
44
36
  end
45
37
 
46
- def self.compare
47
- '#{options[:compare]}'.to_sym
48
- end
49
-
50
38
  include ActiveRecord::ActsHasMany::Child
51
- #{'extend ActiveRecord::ActsHasMany::ChildThrough' if options[:through]}
39
+ #{"extend ActiveRecord::ActsHasMany::ChildThrough" if options[:through]}
52
40
 
53
- def model
54
- #{self}
55
- end
56
-
57
- validates :#{options[:compare]}, uniqueness: true, presence: true
41
+ #{"validates :#{options[:compare]}, uniqueness: true" unless block_given?}
58
42
  EOV
59
43
  end
60
44
 
61
- # Class methods:
62
- # <tt>dependent_relations</tt>
63
- # <tt><relation>_attributes=</tt>
64
- # <tt><relation>_collection=</tt>
65
- # Set:
66
- # after save filter
67
- # attribut accessor tmp_garbage
68
45
  def acts_has_many_for *relations
69
46
  class_eval <<-EOV, __FILE__ , __LINE__ + 1
70
47
  def self.dependent_relations
@@ -78,7 +55,6 @@ module ActiveRecord
78
55
  after_save :clear_garbage
79
56
  EOV
80
57
  end
81
-
82
58
  end
83
59
  end
84
60
  end
@@ -1,3 +1,3 @@
1
1
  module ActsHasMany
2
- VERSION = "0.3.0"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -0,0 +1,134 @@
1
+ shared_examples_for 'acts_has_many' do
2
+ context 'update method' do
3
+ let(:location){Location.create :title => "italy"}
4
+ let(:experience){Experience.create :location => location, :title => "test experience1"}
5
+ before :each do
6
+ Location.delete_all
7
+ Experience.delete_all
8
+ end
9
+
10
+ it 'has_many_update data' do
11
+ add_loc, del_loc = experience.location.has_many_update({"title" => "ukraine"})
12
+
13
+ expect(Location.all.size).to be 1
14
+ expect(location).to eq add_loc
15
+ expect(del_loc).to be nil
16
+ expect(experience.location.title).to eq "ukraine"
17
+
18
+ Experience.create :location => location, :title => "test experience2"
19
+
20
+ add_loc, del_loc = experience.location.has_many_update({"title" => "italy"})
21
+
22
+ expect(Location.all.size).to be 2
23
+ expect(location).not_to eq add_loc
24
+ expect(del_loc).to be nil
25
+
26
+ experience.location = Location.find(add_loc)
27
+ expect(experience.location.title).to eq "italy"
28
+
29
+ add_loc, del_loc = experience.location.has_many_update({"title" => "ukraine"})
30
+
31
+ expect(location).to eq add_loc
32
+ expect(experience.location).to eq del_loc
33
+ end
34
+
35
+ it "parent.child_attributes= Hash" do
36
+ experience = Experience.create location_attributes: {title: "ukraine"}, title: "test experience2"
37
+
38
+ Location.all.size.should be 1
39
+ experience.location.title.should eq "ukraine"
40
+
41
+ Experience.create location_attributes: {title: "ukraine"}, title: "test experience2"
42
+ Location.all.size.should be 1
43
+
44
+ experience.location_attributes = {"title" => "italy"}
45
+ experience.save
46
+
47
+ Location.all.size.should be 2
48
+ experience.location.title.should eq "italy"
49
+
50
+ experience.location_attributes = {"title" => "ukraine"}
51
+ experience.save
52
+
53
+ Location.all.size.should be 1
54
+ experience.location.title.should eq "ukraine"
55
+ end
56
+
57
+ it "parent.child_attributes= exist_record" do
58
+ experience = Experience.create location_attributes: {title: "ukraine"}, title: "test experience2"
59
+
60
+ Location.all.size.should be 1
61
+ experience.location.title.should eq "ukraine"
62
+
63
+ Experience.create location_attributes: Location.first, title: "test experience2"
64
+ Location.all.size.should be 1
65
+
66
+ experience.location_attributes = {"title" => "italy"}
67
+ experience.save
68
+
69
+ Location.all.size.should be 2
70
+ experience.location.title.should eq "italy"
71
+
72
+ experience.location_attributes = Location.first
73
+ experience.save
74
+
75
+ Location.all.size.should be 1
76
+ experience.location.title.should eq "ukraine"
77
+ end
78
+ end
79
+
80
+ it 'destroy' do
81
+ Location.delete_all
82
+ Experience.delete_all
83
+
84
+ location = Location.create(:title => "ukraine")
85
+
86
+ Experience.create( :location => location, :title => "test" )
87
+
88
+ location.destroy
89
+ Location.all.size.should == 1
90
+
91
+ Experience.all[0].destroy
92
+ Location.all.size.should == 0
93
+ end
94
+
95
+ it 'destroy' do
96
+ Location.delete_all
97
+ Experience.delete_all
98
+
99
+ location = Location.create(:title => "ukraine")
100
+
101
+ Experience.create( :location => location, :title => "test" )
102
+
103
+ location.destroy!
104
+ Location.all.size.should == 0
105
+ end
106
+
107
+ it 'actual?' do
108
+ Location.delete_all
109
+
110
+ location = Location.create(:title => "ukraine")
111
+
112
+ location.actual?.should == false
113
+ location.actual?(false).should == false
114
+
115
+ Experience.create( :title => 'test', :location => location )
116
+
117
+ location.actual?.should == false
118
+ location.actual?(false).should == true
119
+
120
+ Experience.create( :title => 'test', :location => location )
121
+
122
+ location.actual?.should == true
123
+ location.actual?(false).should == true
124
+ end
125
+
126
+ it 'dependent_relations' do
127
+ Location.dependent_relations.should == ['experiences']
128
+ end
129
+
130
+ it 'condition' do
131
+ where = Location.condition(:title => "ukraine")
132
+ expect(where).to eq Location.where(:title => "ukraine")
133
+ end
134
+ end
@@ -1,147 +1,64 @@
1
1
  require 'helper'
2
+ require 'has_many_common'
2
3
 
3
- class Location < ActiveRecord::Base
4
- self.table_name = 'locations'
5
- has_many :experiences
4
+ describe "acts_has_many clear initialization" do
5
+ before(:each) do
6
+ Object.send :remove_const, :Location if defined? Location
7
+ class Location < ActiveRecord::Base
8
+ self.table_name = 'locations'
9
+ has_many :experiences
6
10
 
7
- acts_has_many :experiences, compare: 'title'
8
- end
9
-
10
- describe 'acts_has_many' do
11
- context 'update method' do
12
- let(:location){Location.create :title => "italy"}
13
- let(:experience){Experience.create :location => location, :title => "test experience1"}
14
- before :each do
15
- Location.delete_all
16
- Experience.delete_all
17
- end
18
-
19
- it 'has_many_update data' do
20
- add_loc, del_loc = experience.location.has_many_update({"title" => "ukraine"})
21
-
22
- expect(Location.all.size).to be 1
23
- expect(location).to eq add_loc
24
- expect(del_loc).to be nil
25
- expect(experience.location.title).to eq "ukraine"
26
-
27
- Experience.create :location => location, :title => "test experience2"
28
-
29
- add_loc, del_loc = experience.location.has_many_update({"title" => "italy"})
30
-
31
- expect(Location.all.size).to be 2
32
- expect(location).not_to eq add_loc
33
- expect(del_loc).to be nil
34
-
35
- experience.location = Location.find(add_loc)
36
- expect(experience.location.title).to eq "italy"
37
-
38
- add_loc, del_loc = experience.location.has_many_update({"title" => "ukraine"})
39
-
40
- expect(location).to eq add_loc
41
- expect(experience.location).to eq del_loc
42
- end
43
-
44
- it "parent.child_attributes= Hash" do
45
- experience = Experience.create location_attributes: {title: "ukraine"}, title: "test experience2"
46
-
47
- Location.all.size.should be 1
48
- experience.location.title.should eq "ukraine"
49
-
50
- Experience.create location_attributes: {title: "ukraine"}, title: "test experience2"
51
- Location.all.size.should be 1
52
-
53
- experience.location_attributes = {"title" => "italy"}
54
- experience.save
55
-
56
- Location.all.size.should be 2
57
- experience.location.title.should eq "italy"
58
-
59
- experience.location_attributes = {"title" => "ukraine"}
60
- experience.save
61
-
62
- Location.all.size.should be 1
63
- experience.location.title.should eq "ukraine"
64
- end
65
-
66
- it "parent.child_attributes= exist_record" do
67
- experience = Experience.create location_attributes: {title: "ukraine"}, title: "test experience2"
68
-
69
- Location.all.size.should be 1
70
- experience.location.title.should eq "ukraine"
71
-
72
- Experience.create location_attributes: Location.first, title: "test experience2"
73
- Location.all.size.should be 1
74
-
75
- experience.location_attributes = {"title" => "italy"}
76
- experience.save
77
-
78
- Location.all.size.should be 2
79
- experience.location.title.should eq "italy"
80
-
81
- experience.location_attributes = Location.first
82
- experience.save
83
-
84
- Location.all.size.should be 1
85
- experience.location.title.should eq "ukraine"
11
+ acts_has_many
86
12
  end
87
13
  end
14
+ it_behaves_like 'acts_has_many'
15
+ end
88
16
 
89
- it 'destroy' do
90
- Location.delete_all
91
- Experience.delete_all
92
-
93
- location = Location.create(:title => "ukraine")
94
-
95
- Experience.create( :location => location, :title => "test" )
17
+ describe "acts_has_many ititialize with relation" do
18
+ before(:each) do
19
+ Object.send :remove_const, :Location if defined? Location
96
20
 
97
- location.destroy
98
- Location.all.size.should == 1
21
+ class Location < ActiveRecord::Base
22
+ self.table_name = 'locations'
23
+ has_many :experiences
99
24
 
100
- Experience.all[0].destroy
101
- Location.all.size.should == 0
25
+ acts_has_many :experiences
26
+ end
102
27
  end
28
+ it_behaves_like 'acts_has_many'
29
+ end
103
30
 
104
- it 'destroy' do
105
- Location.delete_all
106
- Experience.delete_all
107
-
108
- location = Location.create(:title => "ukraine")
31
+ describe "acts_has_many initialize with :compare" do
32
+ before(:each) do
33
+ Object.send :remove_const, :Location if defined? Location
109
34
 
110
- Experience.create( :location => location, :title => "test" )
35
+ class Location < ActiveRecord::Base
36
+ self.table_name = 'locations'
37
+ has_many :experiences
111
38
 
112
- location.destroy!
113
- Location.all.size.should == 0
39
+ acts_has_many compare: :title
40
+ end
114
41
  end
42
+ it_behaves_like 'acts_has_many'
43
+ end
115
44
 
116
- it 'actual?' do
117
- Location.delete_all
118
-
119
- location = Location.create(:title => "ukraine")
120
-
121
- location.actual?.should == false
122
- location.actual?(false).should == false
123
-
124
- Experience.create( :title => 'test', :location => location )
125
-
126
- location.actual?.should == false
127
- location.actual?(false).should == true
128
-
129
- Experience.create( :title => 'test', :location => location )
45
+ describe "acts_has_many initialize with block" do
46
+ before(:each) do
47
+ Object.send :remove_const, :Location if defined? Location
130
48
 
131
- location.actual?.should == true
132
- location.actual?(false).should == true
133
- end
49
+ class Location < ActiveRecord::Base
50
+ self.table_name = 'locations'
51
+ has_many :experiences
134
52
 
135
- it 'compare' do
136
- Location.compare.should == :title
137
- end
138
-
139
- it 'model' do
140
- location = Location.create(:title => "ukraine")
141
- location.model.should == Location
53
+ acts_has_many do |data|
54
+ where arel_table[:title].eq(data[:title])
55
+ end
56
+ end
142
57
  end
58
+ it_behaves_like 'acts_has_many'
143
59
 
144
- it 'dependent_relations' do
145
- Location.dependent_relations.should == ['experiences']
60
+ it 'condition' do
61
+ where = Location.condition(:title => "ukraine")
62
+ expect(where).to eq Location.where(Location.arel_table[:title].eq("ukraine"))
146
63
  end
147
64
  end
@@ -0,0 +1,94 @@
1
+ shared_examples_for 'acts_has_many through: true' do
2
+ it 'parent.child_colletion=<data>' do
3
+ Local.delete_all
4
+
5
+ company = Company.create title: 'test', locals_collection: [{title: 'testx'}]
6
+ company.locals.first.title.should eq 'testx'
7
+
8
+ company.locals_collection = [{title: 'test2'}]
9
+ company.locals.first.title.should eq 'test2'
10
+ Local.all.size.should be 2
11
+
12
+ company.save # after save we clear garbage
13
+ company.locals.first.title.should eq 'test2'
14
+ Local.all.size.should be 1
15
+
16
+ company2 = Company.create title: 'test2', locals_collection: [{title: 'test2'},{title: 'test1'}]
17
+ company.locals_collection = Local.all
18
+ company.locals.size.should be 2
19
+
20
+ company.save
21
+ Local.all.size.should be 2
22
+
23
+ company.locals_collection = [{title: 'test3'}, {title: 'test2'}]
24
+ company.save
25
+
26
+ company.locals.size.should be 2
27
+ Local.all.size.should be 3
28
+
29
+ company.locals_collection = [{title: 'test1'}]
30
+ Local.all.size.should be 3
31
+
32
+ company.save
33
+ Local.all.size.should be 2
34
+
35
+ company2.locals_collection = [Local.last]
36
+ Local.all.size.should be 2
37
+
38
+ company2.save
39
+ Local.all.size.should be 1
40
+ company2.locals.should eq company.locals
41
+
42
+ company2.locals_collection = []
43
+ company2.save
44
+ company2.locals.should eq []
45
+
46
+ company.locals_collection = []
47
+ company.save
48
+
49
+ Local.all.should eq []
50
+ end
51
+ it 'update' do
52
+ Local.delete_all
53
+
54
+ Local.all.size.should == 0
55
+
56
+ new_records, del_records = Local.has_many_through_update( :new => [
57
+ { title: 'test0'},
58
+ { title: 'test1'},
59
+ { title: 'test2'},
60
+ { title: 'test3'},
61
+ { title: 'test0'},
62
+ ])
63
+
64
+ expect(new_records.count).to be 4
65
+ expect(del_records).to eq []
66
+ expect(Local.all.size).to be 4
67
+
68
+ new_records_1, del_records_1 = Local.has_many_through_update(
69
+ :new => [
70
+ { title: 'test0'},
71
+ { 'title' => 'test1'}
72
+ ],
73
+ :update => {
74
+ new_records[2].id => {title: 'test2s'},
75
+ new_records[3].id.to_s => {'title' => 'test3s'}
76
+ })
77
+
78
+ expect(new_records_1.map(&:id).sort!).to eq new_records.map(&:id)
79
+ expect(Local.find(new_records[2].id).title).to eq 'test2s'
80
+ expect(Local.find(new_records[3].id).title).to eq 'test3s'
81
+ expect(Local.all.size).to be 4
82
+
83
+ new, del = Local.has_many_through_update(
84
+ :new => [
85
+ { title: 'test0'},
86
+ { title: 'test3s'}],
87
+ :update => {
88
+ new_records_1[0].id => {title: 'test0'},
89
+ })
90
+
91
+ expect(del.size).to be 1
92
+ expect(new.size).to be 3
93
+ end
94
+ end
@@ -1,106 +1,96 @@
1
1
  require 'helper'
2
+ require 'has_many_through_common'
2
3
 
3
- class Local < ActiveRecord::Base
4
- self.table_name = 'locals'
5
- has_many :companies, :through => :company_locals
6
- has_many :company_locals
4
+ describe "acts_has_many :through" do
5
+ before(:each) do
6
+ Object.send :remove_const, :Local if defined? Local
7
7
 
8
- acts_has_many :companies, :through => true, compare: 'title'
8
+ class Local < ActiveRecord::Base
9
+ self.table_name = 'locals'
10
+ has_many :companies, :through => :company_locals
11
+ has_many :company_locals
12
+
13
+ acts_has_many through: true
14
+ end
15
+ end
16
+ it_behaves_like 'acts_has_many through: true'
9
17
  end
10
18
 
11
- describe 'acts_has_many with :through' do
12
- it 'parent.child_colletion=<data>' do
13
- Local.delete_all
19
+ describe "acts_has_many :through with relation" do
20
+ before(:each) do
21
+ Object.send :remove_const, :Local if defined? Local
14
22
 
15
- company = Company.create title: 'test', locals_collection: [{title: 'testx'}]
16
- company.locals.first.title.should eq 'testx'
23
+ class Local < ActiveRecord::Base
24
+ self.table_name = 'locals'
25
+ has_many :companies, :through => :company_locals
26
+ has_many :company_locals
17
27
 
18
- company.locals_collection = [{title: 'test2'}]
19
- company.locals.first.title.should eq 'test2'
20
- Local.all.size.should be 2
28
+ acts_has_many :companies, through: true
29
+ end
30
+ end
31
+ it_behaves_like 'acts_has_many through: true'
32
+ end
21
33
 
22
- company.save # after save we clear garbage
23
- company.locals.first.title.should eq 'test2'
24
- Local.all.size.should be 1
34
+ describe "acts_has_many :through with :compare" do
35
+ before(:each) do
36
+ Object.send :remove_const, :Local if defined? Local
25
37
 
26
- company2 = Company.create title: 'test2', locals_collection: [{title: 'test2'},{title: 'test1'}]
27
- company.locals_collection = Local.all
28
- company.locals.size.should be 2
38
+ class Local < ActiveRecord::Base
39
+ self.table_name = 'locals'
40
+ has_many :companies, :through => :company_locals
41
+ has_many :company_locals
29
42
 
30
- company.save
31
- Local.all.size.should be 2
43
+ acts_has_many compare: :title, through: true
44
+ end
45
+ end
46
+ it_behaves_like 'acts_has_many through: true'
47
+ end
32
48
 
33
- company.locals_collection = [{title: 'test3'}, {title: 'test2'}]
34
- company.save
49
+ describe "acts_has_many :through with relation and :compare" do
50
+ before(:each) do
51
+ Object.send :remove_const, :Local if defined? Local
35
52
 
36
- company.locals.size.should be 2
37
- Local.all.size.should be 3
53
+ class Local < ActiveRecord::Base
54
+ self.table_name = 'locals'
55
+ has_many :companies, :through => :company_locals
56
+ has_many :company_locals
38
57
 
39
- company.locals_collection = [{title: 'test1'}]
40
- Local.all.size.should be 3
58
+ acts_has_many :companies, compare: :title, through: true
59
+ end
60
+ end
61
+ it_behaves_like 'acts_has_many through: true'
62
+ end
41
63
 
42
- company.save
43
- Local.all.size.should be 2
64
+ describe "acts_has_many :through with relation and block" do
65
+ before(:each) do
66
+ Object.send :remove_const, :Local if defined? Local
44
67
 
45
- company2.locals_collection = [Local.last]
46
- Local.all.size.should be 2
68
+ class Local < ActiveRecord::Base
69
+ self.table_name = 'locals'
70
+ has_many :companies, :through => :company_locals
71
+ has_many :company_locals
47
72
 
48
- company2.save
49
- Local.all.size.should be 1
50
- company2.locals.should eq company.locals
73
+ acts_has_many :companies, through: true do |local|
74
+ where arel_table[:title].eq local[:title]
75
+ end
76
+ end
77
+ end
78
+ it_behaves_like 'acts_has_many through: true'
79
+ end
51
80
 
52
- company2.locals_collection = []
53
- company2.save
54
- company2.locals.should eq []
81
+ describe "acts_has_many :through with relation and block" do
82
+ before(:each) do
83
+ Object.send :remove_const, :Local if defined? Local
55
84
 
56
- company.locals_collection = []
57
- company.save
85
+ class Local < ActiveRecord::Base
86
+ self.table_name = 'locals'
87
+ has_many :companies, :through => :company_locals
88
+ has_many :company_locals
58
89
 
59
- Local.all.should eq []
60
- end
61
- it 'update' do
62
- Local.delete_all
63
-
64
- Local.all.size.should == 0
65
-
66
- new_records, del_records = Local.has_many_through_update( :new => [
67
- { title: 'test0'},
68
- { title: 'test1'},
69
- { title: 'test2'},
70
- { title: 'test3'},
71
- { title: 'test0'},
72
- ])
73
-
74
- expect(new_records.count).to be 4
75
- expect(del_records).to eq []
76
- expect(Local.all.size).to be 4
77
-
78
- new_records_1, del_records_1 = Local.has_many_through_update(
79
- :new => [
80
- { title: 'test0'},
81
- { 'title' => 'test1'}
82
- ],
83
- :update => {
84
- new_records[2].id => {title: 'test2s'},
85
- new_records[3].id.to_s => {'title' => 'test3s'}
86
- })
87
-
88
- expect(new_records_1.map(&:id).sort!).to eq new_records.map(&:id)
89
- expect(Local.find(new_records[2].id).title).to eq 'test2s'
90
- expect(Local.find(new_records[3].id).title).to eq 'test3s'
91
- expect(Local.all.size).to be 4
92
-
93
-
94
- new, del = Local.has_many_through_update(
95
- :new => [
96
- { title: 'test0'},
97
- { title: 'test3s'}],
98
- :update => {
99
- new_records_1[2].id => {title: 'test2s'},
100
- new_records_1[3].id => {title: ''}
101
- })
102
-
103
- expect(del.size).to be 1
104
- expect(new.size).to be 3
90
+ acts_has_many through: true do |local|
91
+ where arel_table[:title].eq local[:title]
92
+ end
93
+ end
105
94
  end
95
+ it_behaves_like 'acts_has_many through: true'
106
96
  end
metadata CHANGED
@@ -1,94 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_has_many
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
5
- prerelease:
4
+ version: 0.3.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Igor IS04
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-03-20 00:00:00.000000000 Z
11
+ date: 2013-06-05 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
26
  version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: rspec
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: sqlite3
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
76
67
  - !ruby/object:Gem::Version
77
68
  version: '0'
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: activerecord
80
71
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
72
  requirements:
83
- - - ! '>='
73
+ - - '>='
84
74
  - !ruby/object:Gem::Version
85
75
  version: '0'
86
76
  type: :development
87
77
  prerelease: false
88
78
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
79
  requirements:
91
- - - ! '>='
80
+ - - '>='
92
81
  - !ruby/object:Gem::Version
93
82
  version: '0'
94
83
  description: This gem gives functional for update elements has_many relation
@@ -109,35 +98,38 @@ files:
109
98
  - lib/acts_has_many/active_record/acts_has_many/child.rb
110
99
  - lib/acts_has_many/active_record/acts_has_many/parent.rb
111
100
  - lib/acts_has_many/version.rb
101
+ - spec/has_many_common.rb
112
102
  - spec/has_many_spec.rb
103
+ - spec/has_many_through_common.rb
113
104
  - spec/has_many_through_spec.rb
114
105
  - spec/helper.rb
115
106
  homepage: https://github.com/igor04/acts_has_many
116
107
  licenses: []
108
+ metadata: {}
117
109
  post_install_message:
118
110
  rdoc_options: []
119
111
  require_paths:
120
112
  - lib
121
113
  required_ruby_version: !ruby/object:Gem::Requirement
122
- none: false
123
114
  requirements:
124
- - - ! '>='
115
+ - - '>='
125
116
  - !ruby/object:Gem::Version
126
117
  version: '0'
127
118
  required_rubygems_version: !ruby/object:Gem::Requirement
128
- none: false
129
119
  requirements:
130
- - - ! '>='
120
+ - - '>='
131
121
  - !ruby/object:Gem::Version
132
122
  version: '0'
133
123
  requirements: []
134
124
  rubyforge_project:
135
- rubygems_version: 1.8.25
125
+ rubygems_version: 2.0.0
136
126
  signing_key:
137
- specification_version: 3
127
+ specification_version: 4
138
128
  summary: All records must be used, otherwise they will be deleted. Clear logic with
139
129
  has_many
140
130
  test_files:
131
+ - spec/has_many_common.rb
141
132
  - spec/has_many_spec.rb
133
+ - spec/has_many_through_common.rb
142
134
  - spec/has_many_through_spec.rb
143
135
  - spec/helper.rb