Skip to content

Commit

Permalink
Ensure consistent sort order in ActiveModel#serializable_hash when …
Browse files Browse the repository at this point in the history
…using `only` option

This is a bit of a nitpick, but say you do this:

```ruby
user.as_json(only: [:email, :name]).keys
```

The result will depend on the order that the columns were added to your database (or in a test environment, the order of the columns in your `structure.sql`). ie. you might get `["email", "name"]` or `["name", "email"]`.

In the specific case that you've provided `only` you are being explicit about which fields should be returned, so we can also be explicit about the order that they are returned in. This PR implements that. Now it will always return fields based on the order they're provided to the `only` argument, so in this case it would always be `["email", "name"]`.

Co-authored-by: John Hawthorn <[email protected]>
  • Loading branch information
ghiculescu and jhawthorn committed Sep 19, 2024
1 parent 88dc93e commit 0654a61
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 1 deletion.
2 changes: 1 addition & 1 deletion activemodel/lib/active_model/serialization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def serializable_hash(options = nil)
return serializable_attributes(attribute_names) if options.blank?

if only = options[:only]
attribute_names &= Array(only).map(&:to_s)
attribute_names = Array(only).map(&:to_s) & attribute_names
elsif except = options[:except]
attribute_names -= Array(except).map(&:to_s)
end
Expand Down
5 changes: 5 additions & 0 deletions activemodel/test/cases/serialization_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ def test_method_serializable_hash_should_work_with_only_option
assert_equal expected, @user.serializable_hash(only: [:name])
end

def test_method_serializable_hash_should_work_with_only_option_with_order_of_given_keys
expected = { "name" => "David", "email" => "[email protected]" }
assert_equal expected.keys, @user.serializable_hash(only: [:name, :email]).keys
end

def test_method_serializable_hash_should_work_with_except_option
expected = { "gender" => "male", "email" => "[email protected]" }
assert_equal expected, @user.serializable_hash(except: [:name])
Expand Down

0 comments on commit 0654a61

Please sign in to comment.