A long-lived project that still receives updates
Replacement for broken Class.new(ActiveRecord::Base)
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 13
~> 3
~> 1.0, >= 1.0.2
~> 12.1, >= 12.1.1
~> 0.5, >= 0.5.2
>= 1.40
~> 0.9, >= 0.9.34
~> 0.0.10

Runtime

~> 1.1, >= 1.1.4
 Project Readme

AnonymousActiveRecord

License: MIT FOSSA Status Version Downloads Today Depfu CodeCov Test Coverage Maintainability CI Supported Build CI Unsupported Build CI Style Build CI Coverage Build CI Heads Build CI Ancient Build CI Dead Build


Liberapay Patrons Sponsor Me on Github Polar Shield Donate to my FLOSS or refugee efforts at ko-fi.com Donate to my FLOSS or refugee efforts using Patreon

This library was 🎩 inspired by 🎩, the Wolverine project, which implemented a clever workaround to the official non-support of anonymous classes by ActiveRecord.

Warning: Use of this gem is a security risk, due to the use of Ruby's eval. It is intended for use in a test suite, or other non-critical environment.

Project AnonymousActiveRecord
gem name anonymous_active_record
documentation on Github.com, on RDoc.info, on Railsbling.com
code triage Open Source Helpers
expert support Get help on Codementor
... 💖 Liberapay Patrons Sponsor Me Follow Me on LinkedIn Find Me on WellFound: Find Me on CrunchBase My LinkTree Follow Me on Ruby.Social Tweet @ Peter 💻 🌏

Installation

Install the gem and add to the application's Gemfile by executing, adding the --group test on the end if you will only use it for testing (which is the only way it should be used):

$ bundle add anonymous_active_record --group test

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install anonymous_active_record

Compatibility

This gem is compatible with, as of Sep 2024: • Ruby 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3, ruby-head, truffleruby-head

Usage

Require the library in your spec_helper or other test suite boot file.

require "anonymous_active_record"

Let's say you want to write specs for a module, HasBalloon, which provides a method has_balloon?, and will be mixed into ActiveRecord classes.

module HasBalloon
  def has_balloon?
    name == "Spot" # only Spot has a balloon
  end
end

This won't work (really!):

let(:ar_with_balloon) do
  Class.new(ActiveRecord::Base) do
    attr_accessor :name

    include HasBalloon
    def flowery_name
      "#{b_f}#{name}#{b_f}"
    end
    def b_f
      has_balloon? ? "🎈" : "🌸"
    end
  end
end

So do this instead:

let(:ar_with_balloon) do
  AnonymousActiveRecord.generate(columns: ["name"]) do
    include HasBalloon
    def flowery_name
      "#{b_f}#{name}#{b_f}"
    end
    def b_f
      has_balloon? ? "🎈" : "🌸"
    end
  end
end
it "can test the module" do
  expect(ar_with_balloon.new(name: "Spot").flowery_name).to(eq("🎈Spot🎈"))
  expect(ar_with_balloon.new(name: "Not Spot").flowery_name).to(eq("🌸Not Spot🌸"))
end

Generate Options

AnonymousActiveRecord.generate(
  table_name: "a_table_name",
      # if table_name is not set klass_basename will be used to derive a unique random table_name
      # default is a unique random table name
  klass_basename: "anons", # is default
  columns: ["name"],
      # columns default is [],
      # meaning class will have ['id', 'created_at', 'updated_at'], as the AR defaults
      # Optionally provide an array of hashes and thereby designate column type:
      # [{name: 'name', type: 'string'}, {name: 'baked_at', type: 'time'}]
  timestamps: true, # is default
  indexes: [{columns: ["name"], unique: true}],
      # indexes default is [],
      # meaning class will have no indexes, as the AR defaults
      # Optionally provide an array of hashes of index options (similar to those used in Rails migrations):
      # [{columns: ['name'], unique: true}, {columns: ['baked_at']}]
  connection_params: {adapter: "sqlite3", encoding: "utf8", database: ":memory:"}, # is default
) do
   # code which becomes part of the class definition
end

The block is optional.

Factory Options

AnonymousActiveRecord.factory(
  source_data: [{name: "Phil"}, {name: "Vickie"}],
        # Array of hashes, where each hash represents a record that will be created
    # ... The rest of the options are the same as for generate, see above.
) do
  # same as for generate, see above.
end

The block is optional.

There is also a factory! method that will raise if the create fails, accomplished by calling create! instead of create.

🤝 Contributing

See CONTRIBUTING.md

Code Coverage

If you need some ideas of where to help, you could work on adding more code coverage.

Coverage Graph

🌈 Contributors

Contributors

Made with contributors-img.

Star History

Star History Chart

🪇 Code of Conduct

Everyone interacting in this project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.

📌 Versioning

This Library adheres to Semantic Versioning 2.0.0. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions.

To get a better understanding of how SemVer is intended to work over a project's lifetime, read this article from the creator of SemVer:

As a result of this policy, you can (and should) specify a dependency on these libraries using the Pessimistic Version Constraint with two digits of precision.

For example:

spec.add_dependency("anonymous_active_record", "~> 1.0")

See CHANGELOG.md for list of releases.

📄 License

The gem is available as open source under the terms of the MIT License License: MIT. See LICENSE.txt for the official Copyright Notice.

FOSSA Status

© Copyright