Repository is archived
No release in over a year
A patch for Rails to support using a public ID column instead of ID for use with accepts_nested_attributes_for
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

AcceptsNestedAttributesForPublicId

Gem Version CI Status RubyGems Downloads

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 respect to_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