sepastian-mongoid-paranoia-rails4 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ class Address
2
+ include Mongoid::Document
3
+
4
+ field :_id, type: String, default: ->{ street.try(:parameterize) }
5
+
6
+ attr_accessor :mode
7
+
8
+ field :address_type
9
+ field :number, type: Integer
10
+ field :street
11
+ field :city
12
+ field :state
13
+ field :post_code
14
+ field :parent_title
15
+ field :services, type: Array
16
+ field :latlng, type: Array
17
+ field :map, type: Hash
18
+ field :move_in, type: DateTime
19
+ field :s, type: String, as: :suite
20
+ field :name, localize: true
21
+
22
+ embeds_one :code, validate: false
23
+ embeds_one :target, as: :targetable, validate: false
24
+
25
+ embedded_in :addressable, polymorphic: true do
26
+ def extension
27
+ "Testing"
28
+ end
29
+ def doctor?
30
+ title == "Dr"
31
+ end
32
+ end
33
+
34
+ accepts_nested_attributes_for :code, :target
35
+
36
+ belongs_to :account
37
+
38
+ scope :without_postcode, where(postcode: nil)
39
+ scope :rodeo, where(street: "Rodeo Dr") do
40
+ def mansion?
41
+ all? { |address| address.street == "Rodeo Dr" }
42
+ end
43
+ end
44
+
45
+ validates_presence_of :street, on: :update
46
+ validates_format_of :street, with: /\D/, allow_nil: true
47
+
48
+ def set_parent=(set = false)
49
+ self.parent_title = addressable.title if set
50
+ end
51
+
52
+ def <=>(other)
53
+ street <=> other.street
54
+ end
55
+
56
+ class << self
57
+ def california
58
+ where(state: "CA")
59
+ end
60
+
61
+ def homes
62
+ where(address_type: "Home")
63
+ end
64
+
65
+ def streets
66
+ all.map(&:street)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,7 @@
1
+ class Appointment
2
+ include Mongoid::Document
3
+ field :active, type: Boolean, default: true
4
+ field :timed, type: Boolean, default: true
5
+ embedded_in :person
6
+ default_scope where(active: true)
7
+ end
@@ -0,0 +1,6 @@
1
+ class Author
2
+ include Mongoid::Document
3
+ field :name, type: String
4
+
5
+ belongs_to :post, class_name: "ParanoidPost"
6
+ end
@@ -0,0 +1,8 @@
1
+ class Fish
2
+ include Mongoid::Document
3
+ include Mongoid::Paranoia
4
+
5
+ def self.fresh
6
+ where(fresh: true)
7
+ end
8
+ end
@@ -0,0 +1,25 @@
1
+ class ParanoidPhone
2
+ include Mongoid::Document
3
+ include Mongoid::Paranoia
4
+
5
+ attr_accessor :after_destroy_called, :before_destroy_called
6
+
7
+ field :number, type: String
8
+
9
+ embedded_in :person
10
+
11
+ before_destroy :before_destroy_stub, :halt_me
12
+ after_destroy :after_destroy_stub
13
+
14
+ def before_destroy_stub
15
+ self.before_destroy_called = true
16
+ end
17
+
18
+ def after_destroy_stub
19
+ self.after_destroy_called = true
20
+ end
21
+
22
+ def halt_me
23
+ person.age == 42 ? false : true
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ class ParanoidPost
2
+ include Mongoid::Document
3
+ include Mongoid::Paranoia
4
+
5
+ field :title, type: String
6
+
7
+ attr_accessor :after_destroy_called, :before_destroy_called
8
+
9
+ belongs_to :person
10
+
11
+ has_and_belongs_to_many :tags
12
+ has_many :authors, dependent: :delete, inverse_of: :post
13
+ has_many :titles, dependent: :restrict
14
+
15
+ scope :recent, where(created_at: { "$lt" => Time.now, "$gt" => 30.days.ago })
16
+
17
+ before_destroy :before_destroy_stub
18
+ after_destroy :after_destroy_stub
19
+
20
+ def before_destroy_stub
21
+ self.before_destroy_called = true
22
+ end
23
+
24
+ def after_destroy_stub
25
+ self.after_destroy_called = true
26
+ end
27
+
28
+ class << self
29
+ def old
30
+ where(created_at: { "$lt" => 30.days.ago })
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,190 @@
1
+ class Person
2
+ include Mongoid::Document
3
+ attr_accessor :mode
4
+
5
+ class_attribute :somebody_elses_important_class_options
6
+ self.somebody_elses_important_class_options = { keep_me_around: true }
7
+
8
+ field :title
9
+ field :terms, type: Boolean
10
+ field :pets, type: Boolean, default: false
11
+ field :age, type: Integer, default: "100"
12
+ field :dob, type: Date
13
+ field :employer_id
14
+ field :lunch_time, type: Time
15
+ field :aliases, type: Array
16
+ field :map, type: Hash
17
+ field :map_with_default, type: Hash, default: {}
18
+ field :score, type: Integer
19
+ field :blood_alcohol_content, type: Float, default: ->{ 0.0 }
20
+ field :last_drink_taken_at, type: Date, default: ->{ 1.day.ago.in_time_zone("Alaska") }
21
+ field :ssn
22
+ field :owner_id, type: Integer
23
+ field :security_code
24
+ field :reading, type: Object
25
+ field :bson_id, type: Moped::BSON::ObjectId
26
+ field :pattern, type: Regexp
27
+ field :override_me, type: Integer
28
+ field :t, as: :test, type: String
29
+ field :i, as: :inte, type: Integer
30
+ field :a, as: :array, type: Array
31
+ field :desc, localize: true
32
+
33
+ index age: 1
34
+ index addresses: 1
35
+ index dob: 1
36
+ index name: 1
37
+ index title: 1
38
+
39
+ index({ ssn: 1 }, { unique: true })
40
+
41
+ attr_reader :rescored
42
+
43
+ embeds_many :phone_numbers, class_name: "Phone", validate: false
44
+ embeds_many :phones, store_as: :mobile_phones, validate: false
45
+ embeds_many :addresses, as: :addressable, validate: false do
46
+ def extension
47
+ "Testing"
48
+ end
49
+ def find_by_street(street)
50
+ where(street: street).first
51
+ end
52
+ end
53
+
54
+ embeds_many :appointments, validate: false
55
+ embeds_many :paranoid_phones, validate: false
56
+
57
+ embeds_one :passport, autobuild: true, store_as: :pass, validate: false
58
+ embeds_one :pet, class_name: "Animal", validate: false
59
+ embeds_one :name, as: :namable, validate: false do
60
+ def extension
61
+ "Testing"
62
+ end
63
+ def dawkins?
64
+ first_name == "Richard" && last_name == "Dawkins"
65
+ end
66
+ end
67
+ embeds_one :quiz, validate: false
68
+
69
+ has_one :game, dependent: :destroy, validate: false do
70
+ def extension
71
+ "Testing"
72
+ end
73
+ end
74
+
75
+ has_many \
76
+ :posts,
77
+ dependent: :delete,
78
+ validate: false do
79
+ def extension
80
+ "Testing"
81
+ end
82
+ end
83
+ has_many :ordered_posts, order: :rating.desc, validate: false
84
+ has_and_belongs_to_many \
85
+ :preferences,
86
+ index: true,
87
+ dependent: :nullify,
88
+ validate: false
89
+ has_and_belongs_to_many :user_accounts, validate: false
90
+ has_and_belongs_to_many :houses, validate: false
91
+ has_and_belongs_to_many :ordered_preferences, order: :value.desc, validate: false
92
+
93
+ has_many :drugs, validate: false
94
+ has_many :paranoid_posts, validate: false
95
+ has_one :account, validate: false
96
+ has_one :cat, dependent: :nullify, validate: false
97
+ has_one :book, autobuild: true, validate: false
98
+ has_one :home, dependent: :delete, validate: false
99
+
100
+ belongs_to :paranoid_post
101
+
102
+ has_and_belongs_to_many \
103
+ :administrated_events,
104
+ class_name: 'Event',
105
+ inverse_of: :administrators,
106
+ dependent: :nullify,
107
+ validate: false
108
+
109
+ accepts_nested_attributes_for :addresses
110
+ accepts_nested_attributes_for :name, update_only: true
111
+ accepts_nested_attributes_for :pet, allow_destroy: true
112
+ accepts_nested_attributes_for :game, allow_destroy: true
113
+ accepts_nested_attributes_for :posts
114
+ accepts_nested_attributes_for :preferences
115
+ accepts_nested_attributes_for :quiz
116
+ accepts_nested_attributes_for :paranoid_phones
117
+
118
+ scope :minor, where(:age.lt => 18)
119
+ scope :without_ssn, without(:ssn)
120
+ scope :search, ->(query){ any_of({ title: query }) }
121
+
122
+ def score_with_rescoring=(score)
123
+ @rescored = score.to_i + 20
124
+ self.score_without_rescoring = score
125
+ end
126
+
127
+ alias_method_chain :score=, :rescoring
128
+
129
+ def update_addresses
130
+ addresses.each do |address|
131
+ address.street = "Updated Address"
132
+ end
133
+ end
134
+
135
+ def employer=(emp)
136
+ self.employer_id = emp.id
137
+ end
138
+
139
+ def set_addresses=(addresses)
140
+ self.addresses = addresses
141
+ end
142
+
143
+ def override_me
144
+ read_attribute(:override_me).to_s
145
+ end
146
+
147
+ class << self
148
+ def accepted
149
+ scoped.where(terms: true)
150
+ end
151
+ def knight
152
+ scoped.where(title: "Sir")
153
+ end
154
+ def old
155
+ scoped.where(age: { "$gt" => 50 })
156
+ end
157
+ end
158
+
159
+ def reject_if_city_is_empty(attrs)
160
+ attrs[:city].blank?
161
+ end
162
+
163
+ def reject_if_name_is_blank(attrs)
164
+ attrs[:first_name].blank?
165
+ end
166
+
167
+ def foo
168
+ 'i_am_foo'
169
+ end
170
+
171
+ def preference_names=(names)
172
+ names.split(",").each do |name|
173
+ preference = Preference.where(name: name).first
174
+ if preference
175
+ self.preferences << preference
176
+ else
177
+ preferences.build(name: name)
178
+ end
179
+ end
180
+ end
181
+
182
+ def set_on_map_with_default=(value)
183
+ self.map_with_default["key"] = value
184
+ end
185
+
186
+ reset_callbacks(:validate)
187
+ reset_callbacks(:create)
188
+ reset_callbacks(:save)
189
+ reset_callbacks(:destroy)
190
+ end
@@ -0,0 +1,11 @@
1
+ class Phone
2
+ include Mongoid::Document
3
+
4
+ attr_accessor :number_in_observer
5
+
6
+ field :_id, type: String, default: ->{ number }
7
+
8
+ field :number
9
+ embeds_one :country_code
10
+ embedded_in :person
11
+ end
@@ -0,0 +1,6 @@
1
+ class Tag
2
+ include Mongoid::Document
3
+ field :text, type: String
4
+ has_and_belongs_to_many :paranoid_posts
5
+ has_and_belongs_to_many :related, class_name: "Tag", inverse_of: :related
6
+ end
@@ -0,0 +1,4 @@
1
+ class Title
2
+ include Mongoid::Document
3
+ belongs_to :paranoid_post
4
+ end
@@ -0,0 +1,164 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Attributes::Nested do
4
+ describe "##{name}_attributes=" do
5
+ context "when the parent document is new" do
6
+ context "when the relation is an embeds many" do
7
+ context "when ids are passed" do
8
+
9
+ let(:person) do
10
+ Person.create
11
+ end
12
+
13
+ let(:address_one) do
14
+ Address.new(street: "Unter den Linden")
15
+ end
16
+
17
+ let(:address_two) do
18
+ Address.new(street: "Kurfeurstendamm")
19
+ end
20
+
21
+ let(:phone_one) do
22
+ ParanoidPhone.new(number: "1")
23
+ end
24
+
25
+ let(:phone_two) do
26
+ ParanoidPhone.new(number: "2")
27
+ end
28
+
29
+ before do
30
+ person.addresses << [ address_one, address_two ]
31
+ end
32
+
33
+ context "when destroy attributes are passed" do
34
+ context "when the ids match" do
35
+ context "when allow_destroy is true" do
36
+ context "when the child is paranoid" do
37
+
38
+ before(:all) do
39
+ Person.send(:undef_method, :paranoid_phones_attributes=)
40
+ Person.accepts_nested_attributes_for :paranoid_phones,
41
+ allow_destroy: true
42
+ end
43
+
44
+ after(:all) do
45
+ Person.send(:undef_method, :paranoid_phones_attributes=)
46
+ Person.accepts_nested_attributes_for :paranoid_phones
47
+ end
48
+
49
+ [ 1, "1", true, "true" ].each do |truth|
50
+
51
+ context "when passed a #{truth} with destroy" do
52
+ context "when the parent is persisted" do
53
+
54
+ let!(:persisted) do
55
+ Person.create do |p|
56
+ p.paranoid_phones << [ phone_one, phone_two ]
57
+ end
58
+ end
59
+
60
+ context "when setting, pulling, and pushing in one op" do
61
+
62
+ before do
63
+ persisted.paranoid_phones_attributes =
64
+ {
65
+ "bar" => { "id" => phone_one.id, "_destroy" => truth },
66
+ "foo" => { "id" => phone_two.id, "number" => "3" },
67
+ "baz" => { "number" => "4" }
68
+ }
69
+ end
70
+
71
+ it "removes the first document from the relation" do
72
+ persisted.paranoid_phones.size.should eq(2)
73
+ end
74
+
75
+ it "does not delete the unmarked document" do
76
+ persisted.paranoid_phones.first.number.should eq("3")
77
+ end
78
+
79
+ it "adds the new document to the relation" do
80
+ persisted.paranoid_phones.last.number.should eq("4")
81
+ end
82
+
83
+ it "has the proper persisted count" do
84
+ persisted.paranoid_phones.count.should eq(1)
85
+ end
86
+
87
+ it "soft deletes the removed document" do
88
+ phone_one.should be_destroyed
89
+ end
90
+
91
+ context "when saving the parent" do
92
+
93
+ before do
94
+ persisted.with(safe: true).save
95
+ end
96
+
97
+ it "deletes the marked document from the relation" do
98
+ persisted.reload.paranoid_phones.count.should eq(2)
99
+ end
100
+
101
+ it "does not delete the unmarked document" do
102
+ persisted.reload.paranoid_phones.first.number.should eq("3")
103
+ end
104
+
105
+ it "persists the new document to the relation" do
106
+ persisted.reload.paranoid_phones.last.number.should eq("4")
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ context "when the child has defaults" do
116
+
117
+ before(:all) do
118
+ Person.accepts_nested_attributes_for :appointments, allow_destroy: true
119
+ end
120
+
121
+ after(:all) do
122
+ Person.send(:undef_method, :appointments_attributes=)
123
+ end
124
+ context "when the parent is persisted" do
125
+ context "when the child returns false in a before callback" do
126
+ context "when the child is paranoid" do
127
+
128
+ before(:all) do
129
+ Person.accepts_nested_attributes_for :paranoid_phones, allow_destroy: true
130
+ end
131
+
132
+ after(:all) do
133
+ Person.send(:undef_method, :paranoid_phones=)
134
+ Person.accepts_nested_attributes_for :paranoid_phones
135
+ end
136
+
137
+ let!(:persisted) do
138
+ Person.create(age: 42)
139
+ end
140
+
141
+ let!(:phone) do
142
+ persisted.paranoid_phones.create
143
+ end
144
+
145
+ before do
146
+ persisted.paranoid_phones_attributes =
147
+ { "foo" => { "id" => phone.id, "number" => 42, "_destroy" => true }}
148
+ end
149
+
150
+ it "does not destroy the child" do
151
+ persisted.reload.paranoid_phones.should_not be_empty
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end