DenormalizeFields
This gem adds a denormalize
option to ActiveRecord relation definitions, so that updates on one record are forwarded to its dependent records.
Tested on Rails 7, but should work down to Rails 4.1.
Installation
Add, install or require denormalize_fields
.
Usage
Either:
class User < ApplicationRecord
has_many :posts, denormalize: { fields: %i[first_name last_name] }
end
Or:
DenormalizeFields.denormalize(
fields: %i[first_name last_name],
from: User,
onto: :posts,
)
Resulting behavior:
User.first.posts.pluck(:first_name) # => ['Igor', 'Igor']
User.first.update!(first_name: 'Wanja')
User.first.posts.pluck(:first_name) # => ['Wanja', 'Wanja']
Any validation errors in denormalized fields of dependent records are bubbled up to the source record.
There is also a prefix
option:
# assuming there is Rapper#name and Car#owner_name
class Rapper < ApplicationRecord
has_many :cars, denormalize: { fields: :name, prefix: :owner_ } }
end
Alternatively fields
also accepts a Hash
to map to other fields on the related record:
# assuming there is Rapper#name and Car#owner
class Rapper < ApplicationRecord
has_many :cars, denormalize: { fields: { name: :owner } }
end
# multiple fields can be mapped to one, their values will be joined with " "
class Rapper < ApplicationRecord
has_many :cars, denormalize: { fields: { %i[first_name last_name] => :owner } }
end
Conditional denormalization is also supported:
class Blog < ApplicationRecord
# don't remove topic from posts when it is removed from blog
has_many :posts, denormalize: { fields: :topic, if: :topic? }
end
Caveats
- only works with fields that are in the database, no virtual attributes etc.
- does not work with
has_and_belongs_to_many
associations - is based on
ActiveRecord
callbacks, so does not work for#update_column
etc. - does no denormalization when related records are first created / connected
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/jaynetics/denormalize_fields.
License
The gem is available as open source under the terms of the MIT License.
Comparison with similar projects
Most of these have not been updated in years. Let me know if there is any cool new stuff.
-
https://github.com/ursm/activerecord-denormalize
- similar goal
- runs custom SQL, so does not work with all DBs
- skips validations of related records
- only supports
has_many
relations, nothas_one
orbelongs_to
-
https://github.com/bebanjo/persistize
- for denormalization onto the same record or owner record only
-
https://github.com/ignu/denormalize-field
- for denormalization onto the same record or owner record only
- postgres only
-
https://github.com/logandk/mongoid_denormalize
- similar goal
- mongoid only