Automatic created_at and updated_at

I see in the rom-rails there is a way to do this, I am not on rails fortunately.

What would be the best way to have these fields and have them populated and the updated_at field populated on save? at the moment I am manually doing this in my models to_h method, and then using this to persist for example:

class User

def to_h
{

updated_at: Time.now,
created_at: @created_at || Time.now
}
end
end

Which is a bit clunky for me and I could not find any examples out there demonstrating a solution.

Hey Stefan,

Sorry for this late reply. You can use repository with changesets which comes with built-in support for adding timestamps. There’s an example here.

Hope this helps :slight_smile:

2 Likes

The valid link is now http://rom-rb.org/4.0/learn/core/changesets/

3 Likes

Sharing here one example for a repository defined in my Hanami 2.0 app using following version of rom gems

gem 'rom', '~> 5.3'
gem 'rom-sql', '~> 3.6', '>= 3.6.1'

startup_template/db/migrate/20221115100042_create_doctors.rb

# frozen_string_literal: true

ROM::SQL.migration do
  change do
    create_table :doctors do
      primary_key :id
      column :name, :text, null: false
      column :qualification, :text, null: false

      column :created_at, :timestamp
      column :updated_at, :timestamp
    end
  end
end

startup_template/lib/startup_template/repository.rb

# auto_register: false
# frozen_string_literal: true

require 'rom-repository'

module StartupTemplate
  class Repository < ROM::Repository::Root
    include Deps[container: "persistence.rom"]

  end
end

startup_template/lib/startup_template/repositories/doctor_repository.rb

# frozen_string_literal: true

module StartupTemplate
  module Repositories
    class DoctorRepository < Repository[:doctors]

      def create(doctor_attrs_hash)
        changeset = doctors.changeset(:create, doctor_attrs_hash).map(:add_timestamps)
        changeset.commit
      end

    end
  end
end

Usage

startup_template$ HANAMI_ENV=test bundle exec hanami c

startup_template[test]> dr = StartupTemplate::Repositories::DoctorRepository.new
=> #<StartupTemplate::Repositories::DoctorRepository struct_namespace=ROM::Struct auto_struct=true>

startup_template[test]> dr.create({ name: 'Test-Doctor-1', qualification: 'MBBS' })
=> #<ROM::Struct::Doctor id=2 name="Test-Doctor-1" qualification="MBBS" created_at=2022-11-25 14:02:11.355184 +0530 updated_at=2022-11-25 14:02:11.355184 +0530>

startup_template[test]> 

References:

Hope this should prove handy to users visiting this post in future.

Thanks.

1 Like

You can also do this in repositories …

  class MyRepository < ROM::Repository[:relation_name]

    commands :create, update: :by_pk,
      use: :timestamps,
      plugins_options: {timestamps: {timestamps: %i[created_at updated_at]}}

Also …

      .command(:update,
        use: :timestamps,
        plugins_options: {timestamps: {timestamps: %i[created_at updated_at]}})
      .call(data)

This took me awhile to sort out and the double nesting of the options is a little awkward.

1 Like