Skip to content

Commit

Permalink
Aliased fields now work with distinct queries.
Browse files Browse the repository at this point in the history
  • Loading branch information
durran committed Oct 4, 2012
1 parent 3ce8a87 commit d87dabe
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ For instructions on upgrading to newer versions, visit


### Resolved Issues ### Resolved Issues


* mongoid/moped\#82 Aliased fields now work with `Criteria#distinct`.

* \#2423 Fixed embedded document's `update_all` to perform the correct $set * \#2423 Fixed embedded document's `update_all` to perform the correct $set
when using off a criteria. when using off a criteria.


Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/contextual/mongo.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def destroy
# #
# @since 3.0.0 # @since 3.0.0
def distinct(field) def distinct(field)
query.distinct(field) query.distinct(klass.database_field_name(field))
end end


# Iterate over the context. If provided a block, yield to a Mongoid # Iterate over the context. If provided a block, yield to a Mongoid
Expand Down
31 changes: 31 additions & 0 deletions lib/mongoid/fields.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -108,6 +108,21 @@ def attribute_names
self.class.attribute_names self.class.attribute_names
end end


# Get the name of the provided field as it is stored in the database.
# Used in determining if the field is aliased or not.
#
# @example Get the database field name.
# model.database_field_name(:authorization)
#
# @param [ String, Symbol ] name The name to get.
#
# @return [ String ] The name of the field as it's stored in the db.
#
# @since 3.0.7
def database_field_name(name)
self.class.database_field_name(name)
end

# Is the provided field a lazy evaluation? # Is the provided field a lazy evaluation?
# #
# @example If the field is lazy settable. # @example If the field is lazy settable.
Expand Down Expand Up @@ -189,6 +204,22 @@ def attribute_names
fields.keys fields.keys
end end


# Get the name of the provided field as it is stored in the database.
# Used in determining if the field is aliased or not.
#
# @example Get the database field name.
# Model.database_field_name(:authorization)
#
# @param [ String, Symbol ] name The name to get.
#
# @return [ String ] The name of the field as it's stored in the db.
#
# @since 3.0.7
def database_field_name(name)
normalized = name.to_s
aliased_fields[normalized] || normalized
end

# Defines all the fields that are accessible on the Document # Defines all the fields that are accessible on the Document
# For each field that is defined, a getter and setter will be # For each field that is defined, a getter and setter will be
# added as an instance method to the Document. # added as an instance method to the Document.
Expand Down
7 changes: 3 additions & 4 deletions lib/mongoid/indexes.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -115,10 +115,9 @@ def normalize_index_options(options)
# #
# @since 3.0.7 # @since 3.0.7
def normalize_spec(spec) def normalize_spec(spec)
spec.inject({}) do |normal, (name, direction)| spec.inject({}) do |normalized, (name, direction)|
field_name = aliased_fields[name.to_s] || name normalized[database_field_name(name).to_sym] = direction
normal[field_name.to_sym] = direction normalized
normal
end end
end end
end end
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/multi_parameter_attributes.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def process_attributes(attrs = nil, role = :default, guard_protected_attributes
multi_parameter_attributes.each_pair do |key, values| multi_parameter_attributes.each_pair do |key, values|
begin begin
values = (values.keys.min..values.keys.max).map { |i| values[i] } values = (values.keys.min..values.keys.max).map { |i| values[i] }
field = self.class.fields[aliased_fields[key] || key] field = self.class.fields[database_field_name(key)]
attributes[key] = instantiate_object(field, values) attributes[key] = instantiate_object(field, values)
rescue => e rescue => e
errors << Errors::AttributeAssignmentError.new( errors << Errors::AttributeAssignmentError.new(
Expand Down
2 changes: 1 addition & 1 deletion lib/mongoid/persistence.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def update_attribute(name, value)
unless attribute_writable?(normalized) unless attribute_writable?(normalized)
raise Errors::ReadonlyAttribute.new(normalized, value) raise Errors::ReadonlyAttribute.new(normalized, value)
end end
write_attribute(aliased_fields[normalized] || normalized, value) write_attribute(database_field_name(normalized), value)
save(validate: false) save(validate: false)
end end


Expand Down
3 changes: 1 addition & 2 deletions lib/mongoid/validations/uniqueness.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -167,8 +167,7 @@ def filter(value)
# @since 2.3.0 # @since 2.3.0
def scope(criteria, document, attribute) def scope(criteria, document, attribute)
Array.wrap(options[:scope]).each do |item| Array.wrap(options[:scope]).each do |item|
normalized = item.to_s name = document.database_field_name(item)
name = document.aliased_fields[normalized] || normalized
criteria = criteria.where(item => document.attributes[name]) criteria = criteria.where(item => document.attributes[name])
end end
criteria = criteria.where(deleted_at: nil) if document.paranoid? criteria = criteria.where(deleted_at: nil) if document.paranoid?
Expand Down
1 change: 1 addition & 0 deletions spec/app/models/band.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Band
field :upserted, type: Boolean, default: false field :upserted, type: Boolean, default: false
field :created, type: DateTime field :created, type: DateTime
field :sales, type: BigDecimal field :sales, type: BigDecimal
field :y, as: :years, type: Integer


embeds_many :records, cascade_callbacks: true embeds_many :records, cascade_callbacks: true
embeds_many :notes, as: :noteable, cascade_callbacks: true, validate: false embeds_many :notes, as: :noteable, cascade_callbacks: true, validate: false
Expand Down
19 changes: 17 additions & 2 deletions spec/mongoid/contextual/mongo_spec.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@
describe "#distinct" do describe "#distinct" do


before do before do
Band.create(name: "Depeche Mode") Band.create(name: "Depeche Mode", years: 30)
Band.create(name: "New Order") Band.create(name: "New Order", years: 25)
end end


context "when limiting the result set" do context "when limiting the result set" do
Expand Down Expand Up @@ -289,6 +289,21 @@
context.distinct(:name).should eq([ "Depeche Mode", "New Order" ]) context.distinct(:name).should eq([ "Depeche Mode", "New Order" ])
end end
end end

context "when providing an aliased field" do

let(:criteria) do
Band.criteria
end

let(:context) do
described_class.new(criteria)
end

it "returns the distinct field values" do
context.distinct(:years).should eq([ 30, 25 ])
end
end
end end


describe "#each" do describe "#each" do
Expand Down

0 comments on commit d87dabe

Please sign in to comment.