Skip to content

Commit

Permalink
Merge pull request #2471 from Shopify/0-9-stable-warnings
Browse files Browse the repository at this point in the history
Improve attribute methods generation
  • Loading branch information
bf4 authored May 31, 2024
2 parents 92ca1d9 + a6f94c8 commit 597fd24
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 4 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

### [0-9-stable](https://github.com/rails-api/active_model_serializers/compare/v0.9.12...0-9-stable)

- Perf
- [#2471](https://github.com/rails-api/active_model_serializers/pull/2471) Generate better attribute accessors, that also don't trigger warnings when redefined. (@byroot)

### [v0.9.12 (2024-04-11)](https://github.com/rails-api/active_model_serializers/compare/v0.9.11...v0.9.12)

- Fix
Expand Down
4 changes: 3 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,10 @@ group :test do
platforms(*(@windows_platforms + [:ruby])) do
if RUBY_VERSION < '2.5' || version < '6'
gem 'sqlite3', '~> 1.3.13'
elsif version >= '8'
gem 'sqlite3', '>= 2'
else
gem 'sqlite3'
gem 'sqlite3', '< 2'
end
end
platforms :jruby do
Expand Down
18 changes: 15 additions & 3 deletions lib/active_model/serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,27 @@ def root_name
end

def attributes(*attrs)
# Use `class_eval` rather than `define_method` for faster access
# and avoid retaining objects in the closure.
# Batch all methods in a single `class_eval` for efficiceny,
# and define all methods on the same line so the eventual backtrace
# properly maps to the `attributes` call.
source = ["# frozen_string_literal: true\n"]
attrs.each do |attr|
striped_attr = strip_attribute attr

@_attributes << striped_attr

define_method striped_attr do
object.read_attribute_for_serialization attr
end unless method_defined?(attr)
unless method_defined?(attr)
source <<
"def #{striped_attr}" <<
"object.read_attribute_for_serialization(#{attr.inspect})" <<
"end" <<
"alias_method :#{striped_attr}, :#{striped_attr}" # suppress method redefinition warning
end
end
caller = caller_locations(1, 1).first
class_eval(source.join(";"), caller.path, caller.lineno - 1)
end

def has_one(*attrs)
Expand Down

0 comments on commit 597fd24

Please sign in to comment.