{"id":13879172,"url":"https://github.com/pienkowb/active_record-events","last_synced_at":"2025-04-08T12:08:15.041Z","repository":{"id":1566233,"uuid":"42956317","full_name":"pienkowb/active_record-events","owner":"pienkowb","description":"Manage timestamps in ActiveRecord models","archived":false,"fork":false,"pushed_at":"2025-03-02T21:34:22.000Z","size":177,"stargazers_count":134,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"develop","last_synced_at":"2025-04-01T11:02:00.028Z","etag":null,"topics":["activerecord","rails","ruby","ruby-on-rails"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pienkowb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-09-22T19:34:47.000Z","updated_at":"2025-03-02T21:34:08.000Z","dependencies_parsed_at":"2024-09-25T00:24:35.673Z","dependency_job_id":"6c4b290a-3193-4446-9f1c-51d467579961","html_url":"https://github.com/pienkowb/active_record-events","commit_stats":{"total_commits":133,"total_committers":8,"mean_commits":16.625,"dds":"0.17293233082706772","last_synced_commit":"b722dcfb3edc83257f7138107287d719b062a638"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pienkowb%2Factive_record-events","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pienkowb%2Factive_record-events/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pienkowb%2Factive_record-events/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pienkowb%2Factive_record-events/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pienkowb","download_url":"https://codeload.github.com/pienkowb/active_record-events/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247838444,"owners_count":21004580,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activerecord","rails","ruby","ruby-on-rails"],"created_at":"2024-08-06T08:02:12.159Z","updated_at":"2025-04-08T12:08:15.016Z","avatar_url":"https://github.com/pienkowb.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# ActiveRecord::Events [![Gem version](https://img.shields.io/gem/v/active_record-events)](https://rubygems.org/gems/active_record-events) [![Build status](https://img.shields.io/github/actions/workflow/status/pienkowb/active_record-events/test.yml?branch=develop)](https://github.com/pienkowb/active_record-events/actions/workflows/test.yml?query=branch%3Adevelop) [![Coverage status](https://img.shields.io/coveralls/github/pienkowb/active_record-events/develop)](https://coveralls.io/github/pienkowb/active_record-events)\n\nAn ActiveRecord extension providing convenience methods for timestamp management.\n\n## Screencast\n\n\u003ca href=\"https://www.youtube.com/watch?v=TIR7YDF3O-4\"\u003e\n  \u003cimg src=\"https://img.youtube.com/vi/TIR7YDF3O-4/maxresdefault.jpg\" title=\"ActiveRecord::Events - Awesome Ruby Gems\" width=\"50%\"\u003e\n\u003c/a\u003e\n\n[Watch screencast](https://www.youtube.com/watch?v=TIR7YDF3O-4) (courtesy of [Mike Rogers](https://github.com/MikeRogers0))\n\n## Installation\n\nAdd the following line to your application's Gemfile:\n\n```ruby\ngem 'active_record-events'\n```\n\nInstall the gem with Bundler:\n\n```\n$ bundle install\n```\n\nOr do it manually by running:\n\n```\n$ gem install active_record-events\n```\n\n## Usage\n\nRecording a timestamp in order to mark that an event occurred to an object is a common practice when dealing with ActiveRecord models.\nA good example of such an approach is how ActiveRecord handles the `created_at` and `updated_at` fields.\nThis gem allows you to manage custom timestamp fields in the exact same manner.\n\n### Example\n\nConsider a `Task` model with a `completed_at` field and the following methods:\n\n```ruby\nclass Task \u003c ActiveRecord::Base\n  def completed?\n    completed_at.present?\n  end\n\n  def not_completed?\n    !completed?\n  end\n\n  def complete\n    complete! if not_completed?\n  end\n\n  def complete!\n    touch(:completed_at)\n  end\n\n  def self.complete_all\n    touch_all(:completed_at)\n  end\nend\n```\n\nInstead of defining all of these methods by hand, you can use the `has_event` macro provided by the gem.\n\n```ruby\nclass Task \u003c ActiveRecord::Base\n  has_event :complete\nend\n```\n\nAs a result, the methods will be generated automatically.\n\n*It's important to note that the `completed_at` column has to already exist in the database.*\n*Consider [using the generator](#using-a-rails-generator) to create a necessary migration.*\n\n### Scopes\n\nIn addition, the macro defines two scope methods – one for retrieving objects with a recorded timestamp and one for those without it, for example:\n\n```ruby\nscope :not_completed, -\u003e { where(completed_at: nil) }\nscope :completed, -\u003e { where.not(completed_at: nil) }\n```\n\nThe inclusion of scope methods can be omitted by passing the `skip_scopes` flag.\n\n```ruby\nhas_event :complete, skip_scopes: true\n```\n\n### Multiple events\n\nUsing the macro is efficient when more than one field has to be handled that way.\nIn such a case, many lines of code can be replaced with an expressive one-liner.\n\n```ruby\nhas_events :complete, :archive\n```\n\n### Date fields\n\nIn case of date fields, which by convention have names ending with `_on` instead of `_at` (e.g. `completed_on`), the `field_type` option needs to be passed to the macro:\n\n```ruby\nhas_event :complete, field_type: :date\n```\n\n### Custom field name\n\nIf there's a field with a name that doesn't follow the naming convention (i.e. does not end with `_at` or `_on`), you can pass it as the `field_name` option.\n\n```ruby\nhas_event :complete, field_name: :completion_time\n```\n\nNote that the `field_name` option takes precedence over the `field_type` option.\n\n### Comparison strategy\n\nBy default the timestamp's presence will dictate the behavior. However in some cases you may want to check against the current time.\n\nYou can do this with the `strategy` option, which can be either `presence` or `time_comparison`:\n\n```ruby\nhas_event :complete, strategy: :time_comparison\n```\n\n**Example:**\n\n```ruby\ntask.completed_at = 1.hour.ago\ntask.completed? # =\u003e true\n\ntask.completed_at = 1.hour.from_now\ntask.completed? # =\u003e false\n```\n\n### Specifying an object\n\nThere are events which do not relate to a model itself but to one of its attributes – take the `User` model with the `email_confirmed_at` field as an example.\nIn order to keep method names grammatically correct, you can specify an object using the `object` option.\n\n```ruby\nclass User \u003c ActiveRecord::Base\n  has_event :confirm, object: :email\nend\n```\n\nThis will generate the following methods:\n\n- `email_not_confirmed?`\n- `email_confirmed?`\n- `confirm_email`\n- `confirm_email!`\n- `confirm_all_emails` (class method)\n\nAs well as these two scopes:\n\n- `email_confirmed`\n- `email_not_confirmed`\n\n### Using a Rails generator\n\nIf you want to quickly add a new event, you can make use of a Rails generator provided by the gem:\n\n```\n$ rails generate active_record:event task complete\n```\n\nIt will create a necessary migration and insert a `has_event` statement into the model class.\n\n```ruby\n# db/migrate/XXX_add_completed_at_to_tasks.rb\n\nclass AddCompletedAtToTasks \u003c ActiveRecord::Migration[6.0]\n  def change\n    add_column :tasks, :completed_at, :datetime\n  end\nend\n```\n\n```ruby\n# app/models/task.rb\n\nclass Task \u003c ActiveRecord::Base\n  has_event :complete\nend\n```\n\nAll of the macro options are supported by the generator and can be passed via the command line.\nFor instance:\n\n```\n$ rails generate active_record:event user confirm --object=email --skip-scopes\n```\n\nFor more information, run the generator with the `--help` option.\n\n### Overriding methods\n\nIf there's a need to override any of the methods generated by the macro, you can define a new method with the same name in the corresponding model class.\nThis applies to instance methods as well as class methods.\nIn both cases, the `super` keyword invokes the original method.\n\n```ruby\nclass Task \u003c ActiveRecord::Base\n  has_event :complete\n\n  def complete!\n    super\n    logger.info(\"Task #{id} has been completed\")\n  end\n\n  def self.complete_all\n    super\n    logger.info('All tasks have been completed')\n  end\nend\n```\n\n## Contributors\n\n- [Bartosz Pieńkowski](https://github.com/pienkowb)\n- [Tomasz Skupiński](https://github.com/tskupinski)\n- [Oskar Janusz](https://github.com/oskaror)\n- [Mike Rogers](https://github.com/MikeRogers0)\n- [Spencer Rogers](https://github.com/serogers)\n- [Benno Bielmeier](https://github.com/bbenno)\n\n## See also\n\n- [ActiveRecord::Enum](https://api.rubyonrails.org/classes/ActiveRecord/Enum.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpienkowb%2Factive_record-events","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpienkowb%2Factive_record-events","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpienkowb%2Factive_record-events/lists"}