AcceptsNestedAttributesForPublicId
A patch for Rails to support using a public ID column instead of ID for use with accepts_nested_attributes_for
Supports Rails 5, 6, 7+
Why:
- By default ActiveRecord and
accepts_nested_attributes_for
does not respectto_param
or provide any ability to utilize a public ID column. This results in your DB primary keys being exposed in your forms. - This was extracted from a PR to Rails core until this functionality is otherwise achievable in Rails core proper.
DEPRECATED: I am archiving this gem. While this was a good experiment, maintaining this gem is not sustainable. If you wanted to patch this in you would be better off copying this gems code and contract checks techniques directly into your own individual application to ensure that you dont cause breakage. The contract technique did work well but making the gem cross Rails-version compatible was just not really sustainable for a gem.
Installation
gem 'accepts_nested_attributes_for_public_id'
Usage
You now have access to the following options:
Option A: Define a accepts_nested_attributes_for_public_id_column method on your class
class Post < ApplicationRecord
has_many :comments
accepts_nested_attributes_for :comments
end
class Comment < ApplicationRecord
belongs_to :post
def self.accepts_nested_attributes_for_public_id_column
:my_public_id_db_column
end
end
Option B: Use the :public_id_column option on accepts_nested_attributes_for
class Post < ApplicationRecord
has_many :comments
accepts_nested_attributes_for :comments, public_id_column: :my_public_id_db_column
end
class Comment < ApplicationRecord
belongs_to :post
end
How is this safe
The code for Nested Attributes in Rails core has not changed since around Rails 4 (Rails 7.0 is the current release at the time of writing this)
Because this patch requires changes in the very middle of some larger sized methods we are unable to use super
in the patches. This can make it fragile if new changes were introduced to Rails core.
We have taken steps to ensure that no issues are caused by any future Rails changes by adding runtime contracts that ensure the original method source matches our saved contract of the current sources of these methods. If a new Rails version were to change the original method source then you would receive a runtime error stating that we are unable to apply the patch until the gem has been made compatible with any changed code.
Testing
RAILS_ENV=test bundle exec rake db:create
RAILS_ENV=test bundle exec rake db:migrate
bundle exec rspec
We can locally test different versions of Rails using ENV['RAILS_VERSION']
and different database gems using ENV['DB_GEM']
export RAILS_VERSION=7.0
bundle install
bundle exec rspec
Credits
Created & Maintained by Weston Ganger - @westonganger