mongoid 9.0.7 → 9.0.9
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/lib/mongoid/association/embedded/batchable.rb +11 -10
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +64 -29
- data/lib/mongoid/association/nested/many.rb +2 -0
- data/lib/mongoid/association/nested/one.rb +1 -1
- data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +0 -6
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +40 -0
- data/lib/mongoid/association/referenced/has_many/proxy.rb +17 -5
- data/lib/mongoid/attributes.rb +19 -1
- data/lib/mongoid/changeable.rb +10 -1
- data/lib/mongoid/clients/sessions.rb +3 -4
- data/lib/mongoid/config.rb +1 -1
- data/lib/mongoid/contextual/aggregable/mongo.rb +6 -1
- data/lib/mongoid/contextual/mongo.rb +8 -89
- data/lib/mongoid/pluckable.rb +132 -0
- data/lib/mongoid/railties/bson_object_id_serializer.rb +7 -0
- data/lib/mongoid/reloadable.rb +6 -0
- data/lib/mongoid/traversable.rb +0 -2
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/associations/embeds_many_spec.rb +110 -0
- data/spec/integration/associations/has_and_belongs_to_many_spec.rb +81 -0
- data/spec/integration/associations/has_many_spec.rb +56 -0
- data/spec/integration/associations/has_one_spec.rb +55 -3
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +394 -0
- data/spec/mongoid/association/referenced/has_many_models.rb +24 -0
- data/spec/mongoid/association/referenced/has_one_models.rb +10 -2
- data/spec/mongoid/attributes_spec.rb +13 -0
- data/spec/mongoid/clients/transactions_spec.rb +162 -1
- data/spec/mongoid/clients/transactions_spec_models.rb +93 -0
- data/spec/mongoid/contextual/aggregable/mongo_spec.rb +33 -0
- data/spec/mongoid/reloadable_spec.rb +24 -0
- data/spec/shared/CANDIDATE.md +28 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +32 -3
- data/spec/shared/shlib/server.sh +1 -1
- data/spec/support/models/company.rb +2 -0
- data/spec/support/models/passport.rb +1 -0
- data/spec/support/models/product.rb +2 -0
- data/spec/support/models/seo.rb +2 -0
- metadata +7 -4
|
@@ -1819,6 +1819,400 @@ describe Mongoid::Association::Referenced::HasMany::Enumerable do
|
|
|
1819
1819
|
end
|
|
1820
1820
|
end
|
|
1821
1821
|
|
|
1822
|
+
describe '#pluck' do
|
|
1823
|
+
let(:person) do
|
|
1824
|
+
Person.create!
|
|
1825
|
+
end
|
|
1826
|
+
|
|
1827
|
+
let!(:post) do
|
|
1828
|
+
Post.create!(person_id: person.id, title: 'Test Title')
|
|
1829
|
+
end
|
|
1830
|
+
|
|
1831
|
+
let(:base) { Person }
|
|
1832
|
+
let(:association) { Person.relations[:posts] }
|
|
1833
|
+
|
|
1834
|
+
let(:criteria) do
|
|
1835
|
+
Post.where(person_id: person.id)
|
|
1836
|
+
end
|
|
1837
|
+
|
|
1838
|
+
context 'when the enumerable is not loaded' do
|
|
1839
|
+
let!(:enumerable) do
|
|
1840
|
+
described_class.new(criteria, base, association)
|
|
1841
|
+
end
|
|
1842
|
+
|
|
1843
|
+
context 'when the criteria is present' do
|
|
1844
|
+
it 'delegates to the criteria pluck method' do
|
|
1845
|
+
result = enumerable.pluck(:title)
|
|
1846
|
+
expect(result).to eq(['Test Title'])
|
|
1847
|
+
end
|
|
1848
|
+
|
|
1849
|
+
context 'when added docs are present' do
|
|
1850
|
+
it 'combines the results from the criteria and the added docs' do
|
|
1851
|
+
added_post = Post.new(title: 'Added Title', person_id: person.id)
|
|
1852
|
+
enumerable << added_post
|
|
1853
|
+
|
|
1854
|
+
expect(criteria).to receive(:pluck).with(:title).and_return(['Test Title'])
|
|
1855
|
+
result = enumerable.pluck(:title)
|
|
1856
|
+
expect(result).to eq(['Test Title', 'Added Title'])
|
|
1857
|
+
end
|
|
1858
|
+
end
|
|
1859
|
+
end
|
|
1860
|
+
|
|
1861
|
+
context 'when the criteria is not present' do
|
|
1862
|
+
let(:enumerable) { described_class.new([], base, association) }
|
|
1863
|
+
|
|
1864
|
+
it 'returns nothing' do
|
|
1865
|
+
result = enumerable.pluck(:title)
|
|
1866
|
+
expect(result).to eq([])
|
|
1867
|
+
end
|
|
1868
|
+
|
|
1869
|
+
context 'when added docs are present' do
|
|
1870
|
+
it 'returns the values from the added docs' do
|
|
1871
|
+
added_post = Post.new(title: 'Added Title', person_id: person.id)
|
|
1872
|
+
enumerable << added_post
|
|
1873
|
+
|
|
1874
|
+
result = enumerable.pluck(:title)
|
|
1875
|
+
expect(result).to eq(['Added Title'])
|
|
1876
|
+
end
|
|
1877
|
+
end
|
|
1878
|
+
end
|
|
1879
|
+
end
|
|
1880
|
+
|
|
1881
|
+
context 'when the enumerable is loaded' do
|
|
1882
|
+
let(:enumerable) { described_class.new([post], base, association) }
|
|
1883
|
+
|
|
1884
|
+
it 'returns the values from the loaded documents' do
|
|
1885
|
+
result = enumerable.pluck(:title)
|
|
1886
|
+
expect(result).to eq(['Test Title'])
|
|
1887
|
+
end
|
|
1888
|
+
|
|
1889
|
+
context 'when added docs are present' do
|
|
1890
|
+
it 'returns the values from both loaded and added docs' do
|
|
1891
|
+
added_post = Post.new(title: 'Added Title', person_id: person.id)
|
|
1892
|
+
enumerable << added_post
|
|
1893
|
+
|
|
1894
|
+
result = enumerable.pluck(:title)
|
|
1895
|
+
expect(result).to eq(['Test Title', 'Added Title'])
|
|
1896
|
+
end
|
|
1897
|
+
end
|
|
1898
|
+
end
|
|
1899
|
+
end
|
|
1900
|
+
|
|
1901
|
+
describe '#pluck with aliases' do
|
|
1902
|
+
let!(:parent) do
|
|
1903
|
+
Company.create!
|
|
1904
|
+
end
|
|
1905
|
+
|
|
1906
|
+
context 'when the field is aliased' do
|
|
1907
|
+
let!(:expensive) do
|
|
1908
|
+
parent.products.create!(price: 100000)
|
|
1909
|
+
end
|
|
1910
|
+
|
|
1911
|
+
let!(:cheap) do
|
|
1912
|
+
parent.products.create!(price: 1)
|
|
1913
|
+
end
|
|
1914
|
+
|
|
1915
|
+
context 'when using alias_attribute' do
|
|
1916
|
+
|
|
1917
|
+
let(:plucked) do
|
|
1918
|
+
parent.products.pluck(:price)
|
|
1919
|
+
end
|
|
1920
|
+
|
|
1921
|
+
it 'uses the aliases' do
|
|
1922
|
+
expect(plucked).to eq([ 100000, 1 ])
|
|
1923
|
+
end
|
|
1924
|
+
end
|
|
1925
|
+
end
|
|
1926
|
+
|
|
1927
|
+
context 'when plucking a localized field' do
|
|
1928
|
+
with_default_i18n_configs
|
|
1929
|
+
|
|
1930
|
+
before do
|
|
1931
|
+
I18n.locale = :en
|
|
1932
|
+
p = parent.products.create!(name: 'english-text')
|
|
1933
|
+
I18n.locale = :de
|
|
1934
|
+
p.name = 'deutsch-text'
|
|
1935
|
+
p.save!
|
|
1936
|
+
end
|
|
1937
|
+
|
|
1938
|
+
context 'when plucking the entire field' do
|
|
1939
|
+
let(:plucked) do
|
|
1940
|
+
parent.products.all.pluck(:name)
|
|
1941
|
+
end
|
|
1942
|
+
|
|
1943
|
+
let(:plucked_translations) do
|
|
1944
|
+
parent.products.all.pluck(:name_translations)
|
|
1945
|
+
end
|
|
1946
|
+
|
|
1947
|
+
let(:plucked_translations_both) do
|
|
1948
|
+
parent.products.all.pluck(:name_translations, :name)
|
|
1949
|
+
end
|
|
1950
|
+
|
|
1951
|
+
it 'returns the demongoized translations' do
|
|
1952
|
+
expect(plucked.first).to eq('deutsch-text')
|
|
1953
|
+
end
|
|
1954
|
+
|
|
1955
|
+
it 'returns the full translations hash to _translations' do
|
|
1956
|
+
expect(plucked_translations.first).to eq({'de'=>'deutsch-text', 'en'=>'english-text'})
|
|
1957
|
+
end
|
|
1958
|
+
|
|
1959
|
+
it 'returns both' do
|
|
1960
|
+
expect(plucked_translations_both.first).to eq([{'de'=>'deutsch-text', 'en'=>'english-text'}, 'deutsch-text'])
|
|
1961
|
+
end
|
|
1962
|
+
end
|
|
1963
|
+
|
|
1964
|
+
context 'when plucking a specific locale' do
|
|
1965
|
+
|
|
1966
|
+
let(:plucked) do
|
|
1967
|
+
parent.products.all.pluck(:'name.de')
|
|
1968
|
+
end
|
|
1969
|
+
|
|
1970
|
+
it 'returns the specific translations' do
|
|
1971
|
+
expect(plucked.first).to eq('deutsch-text')
|
|
1972
|
+
end
|
|
1973
|
+
end
|
|
1974
|
+
|
|
1975
|
+
context 'when plucking a specific locale from _translations field' do
|
|
1976
|
+
|
|
1977
|
+
let(:plucked) do
|
|
1978
|
+
parent.products.all.pluck(:'name_translations.de')
|
|
1979
|
+
end
|
|
1980
|
+
|
|
1981
|
+
it 'returns the specific translations' do
|
|
1982
|
+
expect(plucked.first).to eq('deutsch-text')
|
|
1983
|
+
end
|
|
1984
|
+
end
|
|
1985
|
+
|
|
1986
|
+
context 'when fallbacks are enabled with a locale list' do
|
|
1987
|
+
require_fallbacks
|
|
1988
|
+
|
|
1989
|
+
before do
|
|
1990
|
+
I18n.fallbacks[:he] = [ :en ]
|
|
1991
|
+
end
|
|
1992
|
+
|
|
1993
|
+
let(:plucked) do
|
|
1994
|
+
parent.products.all.pluck(:name).first
|
|
1995
|
+
end
|
|
1996
|
+
|
|
1997
|
+
it 'correctly uses the fallback' do
|
|
1998
|
+
I18n.locale = :en
|
|
1999
|
+
parent.products.create!(name: 'english-text')
|
|
2000
|
+
I18n.locale = :he
|
|
2001
|
+
expect(plucked).to eq 'english-text'
|
|
2002
|
+
end
|
|
2003
|
+
end
|
|
2004
|
+
|
|
2005
|
+
context 'when the localized field is aliased' do
|
|
2006
|
+
before do
|
|
2007
|
+
I18n.locale = :en
|
|
2008
|
+
parent.products.delete_all
|
|
2009
|
+
p = parent.products.create!(name: 'ACME Rocket Skates', tagline: 'english-text')
|
|
2010
|
+
I18n.locale = :de
|
|
2011
|
+
p.tagline = 'deutsch-text'
|
|
2012
|
+
p.save!
|
|
2013
|
+
end
|
|
2014
|
+
|
|
2015
|
+
context 'when plucking the entire field' do
|
|
2016
|
+
let(:plucked) do
|
|
2017
|
+
parent.products.all.pluck(:tagline)
|
|
2018
|
+
end
|
|
2019
|
+
|
|
2020
|
+
let(:plucked_unaliased) do
|
|
2021
|
+
parent.products.all.pluck(:tl)
|
|
2022
|
+
end
|
|
2023
|
+
|
|
2024
|
+
let(:plucked_translations) do
|
|
2025
|
+
parent.products.all.pluck(:tagline_translations)
|
|
2026
|
+
end
|
|
2027
|
+
|
|
2028
|
+
let(:plucked_translations_both) do
|
|
2029
|
+
parent.products.all.pluck(:tagline_translations, :tagline)
|
|
2030
|
+
end
|
|
2031
|
+
|
|
2032
|
+
it 'returns the demongoized translations' do
|
|
2033
|
+
expect(plucked.first).to eq('deutsch-text')
|
|
2034
|
+
end
|
|
2035
|
+
|
|
2036
|
+
it 'returns the demongoized translations when unaliased' do
|
|
2037
|
+
expect(plucked_unaliased.first).to eq('deutsch-text')
|
|
2038
|
+
end
|
|
2039
|
+
|
|
2040
|
+
it 'returns the full translations hash to _translations' do
|
|
2041
|
+
expect(plucked_translations.first).to eq({ 'de' => 'deutsch-text', 'en' => 'english-text' })
|
|
2042
|
+
end
|
|
2043
|
+
|
|
2044
|
+
it 'returns both' do
|
|
2045
|
+
expect(plucked_translations_both.first).to eq([{ 'de' => 'deutsch-text', 'en' => 'english-text' }, 'deutsch-text'])
|
|
2046
|
+
end
|
|
2047
|
+
end
|
|
2048
|
+
|
|
2049
|
+
context 'when plucking a specific locale' do
|
|
2050
|
+
|
|
2051
|
+
let(:plucked) do
|
|
2052
|
+
parent.products.all.pluck(:'tagline.de')
|
|
2053
|
+
end
|
|
2054
|
+
|
|
2055
|
+
it 'returns the specific translations' do
|
|
2056
|
+
expect(plucked.first).to eq('deutsch-text')
|
|
2057
|
+
end
|
|
2058
|
+
end
|
|
2059
|
+
|
|
2060
|
+
context 'when plucking a specific locale from _translations field' do
|
|
2061
|
+
|
|
2062
|
+
let(:plucked) do
|
|
2063
|
+
parent.products.all.pluck(:'tagline_translations.de')
|
|
2064
|
+
end
|
|
2065
|
+
|
|
2066
|
+
it 'returns the specific translations' do
|
|
2067
|
+
expect(plucked.first).to eq('deutsch-text')
|
|
2068
|
+
end
|
|
2069
|
+
end
|
|
2070
|
+
|
|
2071
|
+
context 'when fallbacks are enabled with a locale list' do
|
|
2072
|
+
require_fallbacks
|
|
2073
|
+
|
|
2074
|
+
before do
|
|
2075
|
+
I18n.fallbacks[:he] = [:en]
|
|
2076
|
+
end
|
|
2077
|
+
|
|
2078
|
+
let(:plucked) do
|
|
2079
|
+
parent.products.all.pluck(:tagline).first
|
|
2080
|
+
end
|
|
2081
|
+
|
|
2082
|
+
it 'correctly uses the fallback' do
|
|
2083
|
+
I18n.locale = :en
|
|
2084
|
+
parent.products.create!(tagline: 'english-text')
|
|
2085
|
+
I18n.locale = :he
|
|
2086
|
+
expect(plucked).to eq 'english-text'
|
|
2087
|
+
end
|
|
2088
|
+
end
|
|
2089
|
+
end
|
|
2090
|
+
|
|
2091
|
+
context 'when the localized field is embedded' do
|
|
2092
|
+
with_default_i18n_configs
|
|
2093
|
+
|
|
2094
|
+
before do
|
|
2095
|
+
s = Seo.new
|
|
2096
|
+
I18n.locale = :en
|
|
2097
|
+
s.name = 'english-text'
|
|
2098
|
+
I18n.locale = :de
|
|
2099
|
+
s.name = 'deutsch-text'
|
|
2100
|
+
|
|
2101
|
+
parent.products.delete_all
|
|
2102
|
+
parent.products.create!(name: 'ACME Tunnel Paint', seo: s)
|
|
2103
|
+
end
|
|
2104
|
+
|
|
2105
|
+
let(:plucked) do
|
|
2106
|
+
parent.products.pluck('seo.name').first
|
|
2107
|
+
end
|
|
2108
|
+
|
|
2109
|
+
let(:plucked_translations) do
|
|
2110
|
+
parent.products.pluck('seo.name_translations').first
|
|
2111
|
+
end
|
|
2112
|
+
|
|
2113
|
+
let(:plucked_translations_field) do
|
|
2114
|
+
parent.products.pluck('seo.name_translations.en').first
|
|
2115
|
+
end
|
|
2116
|
+
|
|
2117
|
+
it 'returns the translation for the current locale' do
|
|
2118
|
+
expect(plucked).to eq('deutsch-text')
|
|
2119
|
+
end
|
|
2120
|
+
|
|
2121
|
+
it 'returns the full _translation hash' do
|
|
2122
|
+
expect(plucked_translations).to eq({ 'en' => 'english-text', 'de' => 'deutsch-text' })
|
|
2123
|
+
end
|
|
2124
|
+
|
|
2125
|
+
it 'returns the translation for the requested locale' do
|
|
2126
|
+
expect(plucked_translations_field).to eq('english-text')
|
|
2127
|
+
end
|
|
2128
|
+
end
|
|
2129
|
+
end
|
|
2130
|
+
|
|
2131
|
+
context 'when the localized field is embedded and aliased' do
|
|
2132
|
+
with_default_i18n_configs
|
|
2133
|
+
|
|
2134
|
+
before do
|
|
2135
|
+
s = Seo.new
|
|
2136
|
+
I18n.locale = :en
|
|
2137
|
+
s.description = 'english-text'
|
|
2138
|
+
I18n.locale = :de
|
|
2139
|
+
s.description = 'deutsch-text'
|
|
2140
|
+
|
|
2141
|
+
parent.products.delete_all
|
|
2142
|
+
parent.products.create!(name: 'ACME Tunnel Paint', seo: s)
|
|
2143
|
+
end
|
|
2144
|
+
|
|
2145
|
+
let(:plucked) do
|
|
2146
|
+
parent.products.pluck('seo.description').first
|
|
2147
|
+
end
|
|
2148
|
+
|
|
2149
|
+
let(:plucked_unaliased) do
|
|
2150
|
+
parent.products.pluck('seo.desc').first
|
|
2151
|
+
end
|
|
2152
|
+
|
|
2153
|
+
let(:plucked_translations) do
|
|
2154
|
+
parent.products.pluck('seo.description_translations').first
|
|
2155
|
+
end
|
|
2156
|
+
|
|
2157
|
+
let(:plucked_translations_field) do
|
|
2158
|
+
parent.products.pluck('seo.description_translations.en').first
|
|
2159
|
+
end
|
|
2160
|
+
|
|
2161
|
+
it 'returns the translation for the current locale' do
|
|
2162
|
+
I18n.with_locale(:en) do
|
|
2163
|
+
expect(plucked).to eq('english-text')
|
|
2164
|
+
end
|
|
2165
|
+
end
|
|
2166
|
+
|
|
2167
|
+
it 'returns the translation for the current locale when unaliased' do
|
|
2168
|
+
I18n.with_locale(:en) do
|
|
2169
|
+
expect(plucked_unaliased).to eq('english-text')
|
|
2170
|
+
end
|
|
2171
|
+
end
|
|
2172
|
+
|
|
2173
|
+
it 'returns the full _translation hash' do
|
|
2174
|
+
expect(plucked_translations).to eq({ 'en' => 'english-text', 'de' => 'deutsch-text' })
|
|
2175
|
+
end
|
|
2176
|
+
|
|
2177
|
+
it 'returns the translation for the requested locale' do
|
|
2178
|
+
expect(plucked_translations_field).to eq('english-text')
|
|
2179
|
+
end
|
|
2180
|
+
end
|
|
2181
|
+
|
|
2182
|
+
context 'when plucking an embedded field' do
|
|
2183
|
+
let(:label) { Label.new(sales: '1E2') }
|
|
2184
|
+
let!(:band) { Band.create!(label: label) }
|
|
2185
|
+
|
|
2186
|
+
let(:plucked) { Band.where(_id: band.id).pluck('label.sales') }
|
|
2187
|
+
|
|
2188
|
+
it 'demongoizes the field' do
|
|
2189
|
+
expect(plucked).to eq([ BigDecimal('1E2') ])
|
|
2190
|
+
end
|
|
2191
|
+
end
|
|
2192
|
+
|
|
2193
|
+
context 'when plucking an embeds_many field' do
|
|
2194
|
+
let(:label) { Label.new(sales: '1E2') }
|
|
2195
|
+
let!(:band) { Band.create!(labels: [label]) }
|
|
2196
|
+
|
|
2197
|
+
let(:plucked) { Band.where(_id: band.id).pluck('labels.sales') }
|
|
2198
|
+
|
|
2199
|
+
it 'demongoizes the field' do
|
|
2200
|
+
expect(plucked.first).to eq([ BigDecimal('1E2') ])
|
|
2201
|
+
end
|
|
2202
|
+
end
|
|
2203
|
+
|
|
2204
|
+
context 'when plucking a nonexistent embedded field' do
|
|
2205
|
+
let(:label) { Label.new(sales: '1E2') }
|
|
2206
|
+
let!(:band) { Band.create!(label: label) }
|
|
2207
|
+
|
|
2208
|
+
let(:plucked) { Band.where(_id: band.id).pluck('label.qwerty') }
|
|
2209
|
+
|
|
2210
|
+
it 'returns nil' do
|
|
2211
|
+
expect(plucked.first).to eq(nil)
|
|
2212
|
+
end
|
|
2213
|
+
end
|
|
2214
|
+
end
|
|
2215
|
+
|
|
1822
2216
|
describe "#reset" do
|
|
1823
2217
|
|
|
1824
2218
|
let(:person) do
|
|
@@ -96,3 +96,27 @@ class HmmAnimal
|
|
|
96
96
|
|
|
97
97
|
belongs_to :trainer, class_name: 'HmmTrainer', scope: -> { where(name: 'Dave') }
|
|
98
98
|
end
|
|
99
|
+
|
|
100
|
+
class HmmPost
|
|
101
|
+
include Mongoid::Document
|
|
102
|
+
|
|
103
|
+
field :title, type: String
|
|
104
|
+
|
|
105
|
+
has_many :comments, class_name: 'HmmComment', as: :container
|
|
106
|
+
|
|
107
|
+
accepts_nested_attributes_for :comments, allow_destroy: true
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
class HmmComment
|
|
111
|
+
include Mongoid::Document
|
|
112
|
+
|
|
113
|
+
field :title, type: String
|
|
114
|
+
field :num, type: Integer, default: 0
|
|
115
|
+
|
|
116
|
+
belongs_to :container, polymorphic: true
|
|
117
|
+
has_many :comments, class_name: 'HmmComment', as: :container
|
|
118
|
+
|
|
119
|
+
accepts_nested_attributes_for :comments, allow_destroy: true
|
|
120
|
+
|
|
121
|
+
validates :num, numericality: { greater_than_or_equal_to: 0 }
|
|
122
|
+
end
|
|
@@ -102,13 +102,21 @@ class HomPost
|
|
|
102
102
|
|
|
103
103
|
field :title, type: String
|
|
104
104
|
|
|
105
|
-
has_one :comment,
|
|
105
|
+
has_one :comment, as: :container, class_name: 'HomComment'
|
|
106
|
+
|
|
107
|
+
accepts_nested_attributes_for :comment, allow_destroy: true
|
|
106
108
|
end
|
|
107
109
|
|
|
108
110
|
class HomComment
|
|
109
111
|
include Mongoid::Document
|
|
110
112
|
|
|
111
113
|
field :content, type: String
|
|
114
|
+
field :num, type: Integer, default: 0
|
|
115
|
+
|
|
116
|
+
validates :num, numericality: { greater_than_or_equal_to: 0 }
|
|
117
|
+
|
|
118
|
+
belongs_to :container, polymorphic: true, optional: true
|
|
119
|
+
has_one :comment, as: :container, class_name: 'HomComment'
|
|
112
120
|
|
|
113
|
-
|
|
121
|
+
accepts_nested_attributes_for :comment, allow_destroy: true
|
|
114
122
|
end
|
|
@@ -1729,6 +1729,19 @@ describe Mongoid::Attributes do
|
|
|
1729
1729
|
end
|
|
1730
1730
|
end
|
|
1731
1731
|
end
|
|
1732
|
+
|
|
1733
|
+
context 'when map_big_decimal_to_decimal128 is enabled' do
|
|
1734
|
+
config_override :map_big_decimal_to_decimal128, true
|
|
1735
|
+
|
|
1736
|
+
context 'when writing an identical number' do
|
|
1737
|
+
let(:band) { Band.create!(name: 'Nirvana', sales: 123456.78).reload }
|
|
1738
|
+
|
|
1739
|
+
it 'does not mark the document as changed' do
|
|
1740
|
+
band.sales = 123456.78
|
|
1741
|
+
expect(band.changed?).to be false
|
|
1742
|
+
end
|
|
1743
|
+
end
|
|
1744
|
+
end
|
|
1732
1745
|
end
|
|
1733
1746
|
|
|
1734
1747
|
describe "#typed_value_for" do
|
|
@@ -716,7 +716,7 @@ describe Mongoid::Clients::Sessions do
|
|
|
716
716
|
require_transaction_support
|
|
717
717
|
|
|
718
718
|
context 'when no error raised' do
|
|
719
|
-
|
|
719
|
+
let!(:person) do
|
|
720
720
|
Mongoid.transaction do
|
|
721
721
|
Person.create!
|
|
722
722
|
end
|
|
@@ -727,6 +727,10 @@ describe Mongoid::Clients::Sessions do
|
|
|
727
727
|
expect(other_events.count { |e| e.command_name == 'commitTransaction'}).to be(1)
|
|
728
728
|
end
|
|
729
729
|
|
|
730
|
+
it 'returns the value from the block' do
|
|
731
|
+
expect(person).to be_a(Person)
|
|
732
|
+
end
|
|
733
|
+
|
|
730
734
|
it 'executes the commands inside the transaction' do
|
|
731
735
|
expect(Person.count).to be(1)
|
|
732
736
|
end
|
|
@@ -787,8 +791,12 @@ describe Mongoid::Clients::Sessions do
|
|
|
787
791
|
Mongoid::Clients.with_name(:default).database.collections.each(&:drop)
|
|
788
792
|
TransactionsSpecPerson.collection.create
|
|
789
793
|
TransactionsSpecPersonWithOnCreate.collection.create
|
|
794
|
+
TransactionsSpecPersonWithAfterCreateCommit.collection.create
|
|
790
795
|
TransactionsSpecPersonWithOnUpdate.collection.create
|
|
796
|
+
TransactionsSpecPersonWithAfterUpdateCommit.collection.create
|
|
797
|
+
TransactionsSpecPersonWithAfterSaveCommit.collection.create
|
|
791
798
|
TransactionsSpecPersonWithOnDestroy.collection.create
|
|
799
|
+
TransactionsSpecPersonWithAfterDestroyCommit.collection.create
|
|
792
800
|
TransactionSpecRaisesBeforeSave.collection.create
|
|
793
801
|
TransactionSpecRaisesAfterSave.collection.create
|
|
794
802
|
end
|
|
@@ -818,6 +826,18 @@ describe Mongoid::Clients::Sessions do
|
|
|
818
826
|
|
|
819
827
|
it_behaves_like 'commit callbacks are called'
|
|
820
828
|
end
|
|
829
|
+
|
|
830
|
+
context 'when callback is after_create_commit' do
|
|
831
|
+
let!(:subject) do
|
|
832
|
+
person = nil
|
|
833
|
+
TransactionsSpecPersonWithAfterCreateCommit.transaction do
|
|
834
|
+
person = TransactionsSpecPersonWithAfterCreateCommit.create!(name: 'James Bond')
|
|
835
|
+
end
|
|
836
|
+
person
|
|
837
|
+
end
|
|
838
|
+
|
|
839
|
+
it_behaves_like 'commit callbacks are called'
|
|
840
|
+
end
|
|
821
841
|
end
|
|
822
842
|
|
|
823
843
|
context 'save' do
|
|
@@ -886,6 +906,94 @@ describe Mongoid::Clients::Sessions do
|
|
|
886
906
|
it_behaves_like 'commit callbacks are called'
|
|
887
907
|
end
|
|
888
908
|
end
|
|
909
|
+
|
|
910
|
+
context 'with after_update_commit callback' do
|
|
911
|
+
let(:subject) do
|
|
912
|
+
TransactionsSpecPersonWithAfterUpdateCommit.create!(name: 'James Bond').tap do |subject|
|
|
913
|
+
subject.after_commit_counter.reset
|
|
914
|
+
subject.after_rollback_counter.reset
|
|
915
|
+
end
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
context 'when modified once' do
|
|
919
|
+
before do
|
|
920
|
+
subject.transaction do
|
|
921
|
+
subject.name = 'Austin Powers'
|
|
922
|
+
subject.save!
|
|
923
|
+
end
|
|
924
|
+
end
|
|
925
|
+
|
|
926
|
+
it_behaves_like 'commit callbacks are called'
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
context 'when modified multiple times' do
|
|
930
|
+
before do
|
|
931
|
+
subject.transaction do
|
|
932
|
+
subject.name = 'Austin Powers'
|
|
933
|
+
subject.save!
|
|
934
|
+
subject.name = 'Jason Bourne'
|
|
935
|
+
subject.save!
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
it_behaves_like 'commit callbacks are called'
|
|
940
|
+
end
|
|
941
|
+
end
|
|
942
|
+
|
|
943
|
+
context 'with after_save_commit callback' do
|
|
944
|
+
let(:subject) do
|
|
945
|
+
TransactionsSpecPersonWithAfterSaveCommit.create!(name: 'James Bond').tap do |subject|
|
|
946
|
+
subject.after_commit_counter.reset
|
|
947
|
+
subject.after_rollback_counter.reset
|
|
948
|
+
end
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
context 'when modified once' do
|
|
952
|
+
before do
|
|
953
|
+
subject.transaction do
|
|
954
|
+
subject.name = 'Austin Powers'
|
|
955
|
+
subject.save!
|
|
956
|
+
end
|
|
957
|
+
end
|
|
958
|
+
|
|
959
|
+
it_behaves_like 'commit callbacks are called'
|
|
960
|
+
end
|
|
961
|
+
|
|
962
|
+
context 'when created' do
|
|
963
|
+
before do
|
|
964
|
+
TransactionsSpecPersonWithAfterSaveCommit.transaction do
|
|
965
|
+
subject
|
|
966
|
+
end
|
|
967
|
+
end
|
|
968
|
+
|
|
969
|
+
it_behaves_like 'commit callbacks are called'
|
|
970
|
+
end
|
|
971
|
+
|
|
972
|
+
context 'when modified multiple times' do
|
|
973
|
+
before do
|
|
974
|
+
subject.transaction do
|
|
975
|
+
subject.name = 'Austin Powers'
|
|
976
|
+
subject.save!
|
|
977
|
+
subject.name = 'Jason Bourne'
|
|
978
|
+
subject.save!
|
|
979
|
+
end
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
it_behaves_like 'commit callbacks are called'
|
|
983
|
+
end
|
|
984
|
+
|
|
985
|
+
context 'when created and modified' do
|
|
986
|
+
before do
|
|
987
|
+
TransactionsSpecPersonWithAfterSaveCommit.transaction do
|
|
988
|
+
subject
|
|
989
|
+
subject.name = 'Jason Bourne'
|
|
990
|
+
subject.save!
|
|
991
|
+
end
|
|
992
|
+
end
|
|
993
|
+
|
|
994
|
+
it_behaves_like 'commit callbacks are called'
|
|
995
|
+
end
|
|
996
|
+
end
|
|
889
997
|
end
|
|
890
998
|
|
|
891
999
|
context 'update_attributes' do
|
|
@@ -919,6 +1027,34 @@ describe Mongoid::Clients::Sessions do
|
|
|
919
1027
|
|
|
920
1028
|
it_behaves_like 'commit callbacks are called'
|
|
921
1029
|
end
|
|
1030
|
+
|
|
1031
|
+
context 'when callback is after_update_commit' do
|
|
1032
|
+
let(:subject) do
|
|
1033
|
+
TransactionsSpecPersonWithAfterUpdateCommit.create!(name: 'Jason Bourne')
|
|
1034
|
+
end
|
|
1035
|
+
|
|
1036
|
+
before do
|
|
1037
|
+
TransactionsSpecPersonWithAfterUpdateCommit.transaction do
|
|
1038
|
+
subject.update_attributes!(name: 'Foma Kiniaev')
|
|
1039
|
+
end
|
|
1040
|
+
end
|
|
1041
|
+
|
|
1042
|
+
it_behaves_like 'commit callbacks are called'
|
|
1043
|
+
end
|
|
1044
|
+
|
|
1045
|
+
context 'when callback is after_save_commit' do
|
|
1046
|
+
let(:subject) do
|
|
1047
|
+
TransactionsSpecPersonWithAfterSaveCommit.create!(name: 'Jason Bourne')
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
before do
|
|
1051
|
+
TransactionsSpecPersonWithAfterSaveCommit.transaction do
|
|
1052
|
+
subject.update_attributes!(name: 'Foma Kiniaev')
|
|
1053
|
+
end
|
|
1054
|
+
end
|
|
1055
|
+
|
|
1056
|
+
it_behaves_like 'commit callbacks are called'
|
|
1057
|
+
end
|
|
922
1058
|
end
|
|
923
1059
|
|
|
924
1060
|
context 'destroy' do
|
|
@@ -971,6 +1107,31 @@ describe Mongoid::Clients::Sessions do
|
|
|
971
1107
|
|
|
972
1108
|
it_behaves_like 'commit callbacks are called'
|
|
973
1109
|
end
|
|
1110
|
+
|
|
1111
|
+
context 'with after_destroy_commit' do
|
|
1112
|
+
let(:after_commit_counter) do
|
|
1113
|
+
TransactionsSpecCounter.new
|
|
1114
|
+
end
|
|
1115
|
+
|
|
1116
|
+
let(:after_rollback_counter) do
|
|
1117
|
+
TransactionsSpecCounter.new
|
|
1118
|
+
end
|
|
1119
|
+
|
|
1120
|
+
let(:subject) do
|
|
1121
|
+
TransactionsSpecPersonWithAfterDestroyCommit.create!(name: 'James Bond').tap do |p|
|
|
1122
|
+
p.after_commit_counter = after_commit_counter
|
|
1123
|
+
p.after_rollback_counter = after_rollback_counter
|
|
1124
|
+
end
|
|
1125
|
+
end
|
|
1126
|
+
|
|
1127
|
+
before do
|
|
1128
|
+
subject.transaction do
|
|
1129
|
+
subject.destroy
|
|
1130
|
+
end
|
|
1131
|
+
end
|
|
1132
|
+
|
|
1133
|
+
it_behaves_like 'commit callbacks are called'
|
|
1134
|
+
end
|
|
974
1135
|
end
|
|
975
1136
|
end
|
|
976
1137
|
|