Dirk Dot Net

Creator of useful things. Based in Chiang Mai, Northern Thailand.

Custom Primary Key and Mass Assignment

Say you have an ActiveRecord model with a custom primary key and no field named “id”, a common occurrence when working with legacy data:


class Hotel < ActiveRecord::Base
set_primary_key :hotel_id


Now you have the pertinent form

<% form_for(@hotel) do |f| %>
<%= f.error_messages %>

<%= f.label 'Hotel ID' %>:
<%= f.text_field :hotel_id %>

<%= f.label 'Name' %>:
<%= f.text_field :name %>

<%= f.label 'Destination ID' %>:
<%= f.text_field :destination_id %>

<%= f.submit 'Save' %>

<% end %>

and default controller code:


def create
@hotel = Hotel.new(params[:hotel])

respond_to do |format|

if @hotel.save


However, this won’t work. The mass assignment at

@hotel = Hotel.new(params[:hotel])

can’t be used with a “custom” primary key as this code called by the initializer excludes the primary key:


def attributes_from_column_definition
self.class.columns.inject({}) do |attributes, column|
attributes[column.name] = column.default **unless column.name == self.class.primary_key
** attributes

It is therefore necessary to call the initializer (Hotel.new) without the params hash and set the attributes manually:


def create
@hotel = Hotel.new
my_params = params[:hotel]
@hotel.hotel_id = my_params[:hotel_id]
@hotel.name_english = my_params[:name]
@hotel.destination_id = my_params[:destination_id]

respond_to do |format|
if @hotel.save