{"id":14991253,"url":"https://github.com/casecommons/with_model","last_synced_at":"2025-05-14T23:04:53.971Z","repository":{"id":1235313,"uuid":"1171621","full_name":"Casecommons/with_model","owner":"Casecommons","description":"Dynamically build an Active Record model (with table) within a test context","archived":false,"fork":false,"pushed_at":"2025-02-04T17:02:26.000Z","size":285,"stargazers_count":178,"open_issues_count":3,"forks_count":18,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-05-14T23:04:46.676Z","etag":null,"topics":["activerecord","minitest","rspec","ruby","testing"],"latest_commit_sha":null,"homepage":"http://www.casebook.net","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/Casecommons.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2010-12-15T16:36:29.000Z","updated_at":"2025-04-28T15:10:48.000Z","dependencies_parsed_at":"2025-01-19T16:00:26.648Z","dependency_job_id":"b811629d-d47b-4909-8aad-0cb61e7f8f8f","html_url":"https://github.com/Casecommons/with_model","commit_stats":{"total_commits":402,"total_committers":29,"mean_commits":"13.862068965517242","dds":0.5646766169154229,"last_synced_commit":"15f50230b6a53f53bc5b432c4f12ebe0880c2479"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Casecommons%2Fwith_model","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Casecommons%2Fwith_model/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Casecommons%2Fwith_model/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Casecommons%2Fwith_model/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Casecommons","download_url":"https://codeload.github.com/Casecommons/with_model/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254243358,"owners_count":22038046,"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","minitest","rspec","ruby","testing"],"created_at":"2024-09-24T14:22:00.993Z","updated_at":"2025-05-14T23:04:48.941Z","avatar_url":"https://github.com/Casecommons.png","language":"Ruby","readme":"# [with_model](https://github.com/Casecommons/with_model)\n\n[![Gem Version](https://img.shields.io/gem/v/with_model.svg?style=flat)](https://rubygems.org/gems/with_model)\n[![Build Status](https://github.com/Casecommons/with_model/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/Casecommons/with_model/actions/workflows/ci.yml)\n[![API Documentation](https://img.shields.io/badge/yard-api%20docs-lightgrey.svg)](https://www.rubydoc.info/gems/with_model)\n\n`with_model` dynamically builds an Active Record model (with table) before each test in a group and destroys it afterwards.\n\n## Development status\n\n`with_model` is actively maintained. It is quite stable, so while updates may appear infrequent, it is only because none are needed.\n\n## Installation\n\nInstall as usual: `gem install with_model` or add `gem 'with_model'` to your Gemfile. See [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) for supported (tested) Ruby versions.\n\n### RSpec\n\nExtend `WithModel` into RSpec:\n\n```ruby\nrequire 'with_model'\n\nRSpec.configure do |config|\n  config.extend WithModel\nend\n```\n\n### minitest/spec\n\nExtend `WithModel` into minitest/spec and set the test runner explicitly:\n\n```ruby\nrequire 'with_model'\n\nWithModel.runner = :minitest\n\nclass Minitest::Spec\n  extend WithModel\nend\n```\n\n## Usage\n\nAfter setting up as above, call `with_model` and inside its block pass it a `table` block and a `model` block.\n\n```ruby\nrequire 'spec_helper'\n\ndescribe \"A blog post\" do\n  module MyModule; end\n\n  with_model :BlogPost do\n    # The table block (and an options hash) is passed to Active Record migration’s `create_table`.\n    table do |t|\n      t.string :title\n      t.timestamps null: false\n    end\n\n    # The model block is the Active Record model’s class body.\n    model do\n      include MyModule\n      has_many :comments\n      validates_presence_of :title\n\n      def self.some_class_method\n        'chunky'\n      end\n\n      def some_instance_method\n        'bacon'\n      end\n    end\n  end\n\n  # with_model classes can have associations.\n  with_model :Comment do\n    table do |t|\n      t.string :text\n      t.belongs_to :blog_post\n      t.timestamps null: false\n    end\n\n    model do\n      belongs_to :blog_post\n    end\n  end\n\n  it \"can be accessed as a constant\" do\n    expect(BlogPost).to be\n  end\n\n  it \"has the module\" do\n    expect(BlogPost.include?(MyModule)).to eq true\n  end\n\n  it \"has the class method\" do\n    expect(BlogPost.some_class_method).to eq 'chunky'\n  end\n\n  it \"has the instance method\" do\n    expect(BlogPost.new.some_instance_method).to eq 'bacon'\n  end\n\n  it \"can do all the things a regular model can\" do\n    record = BlogPost.new\n    expect(record).not_to be_valid\n    record.title = \"foo\"\n    expect(record).to be_valid\n    expect(record.save).to eq true\n    expect(record.reload).to eq record\n    record.comments.create!(:text =\u003e \"Lorem ipsum\")\n    expect(record.comments.count).to eq 1\n  end\n\n  # with_model classes can have inheritance.\n  class Car \u003c ActiveRecord::Base\n    self.abstract_class = true\n  end\n\n  with_model :Ford, superclass: Car do\n  end\n\n  it \"has a specified superclass\" do\n    expect(Ford \u003c Car).to eq true\n  end\nend\n\ndescribe \"with_model can be run within RSpec :all hook\" do\n  with_model :BlogPost, scope: :all do\n    table do |t|\n      t.string :title\n    end\n  end\n\n  before :all do\n    BlogPost.create # without scope: :all these will fail\n  end\n\n  it \"has been initialized within before(:all)\" do\n    expect(BlogPost.count).to eq 1\n  end\nend\n\ndescribe \"another example group\" do\n  it \"does not have the constant anymore\" do\n    expect(defined?(BlogPost)).to be_falsy\n  end\nend\n\ndescribe \"with table options\" do\n  with_model :WithOptions do\n    table :id =\u003e false do |t|\n      t.string 'foo'\n      t.timestamps null: false\n    end\n  end\n\n  it \"respects the additional options\" do\n    expect(WithOptions.columns.map(\u0026:name)).not_to include(\"id\")\n  end\nend\n```\n\n## Requirements\n\nSee the [gemspec metadata](https://rubygems.org/gems/with_model) for dependency requirements. RSpec and minitest are indirect dependencies, and `with_model` should support any maintained version of both.\n\n## Thread-safety\n\n- A unique table name is used for tables generated via `with_model`/`WithModel::Model.new`. This allows `with_model` (when limited to this API) to run concurrently (in processes or threads) with a single database schema. While there is a possibility of collision, it is very small.\n- A user-supplied table name is used for tables generated via `with_table`/`WithModel::Table.new`. This may cause collisions at runtime if tests are run concurrently against a single database schema, unless the caller takes care to ensure the table names passed as arguments are unique across threads/processes.\n- Generated models are created in stubbed constants, which are global; no guarantee is made to the uniqueness of a constant, and this may be unsafe.\n- Generated classes are Active Record subclasses:\n  - This library makes no guarantee as to the thread-safety of creating Active Record subclasses concurrently.\n  - This library makes no guarantee as to the thread-safety of cleaning up Active Record/Active Support’s internals which are polluted upon class creation.\n\nIn general, `with_model` is not guaranteed to be thread-safe, but is, in certain usages, safe to use concurrently across multiple processes with a single database schema.\n\n## Versioning\n\n`with_model` uses [Semantic Versioning 2.0.0](http://semver.org/spec/v2.0.0.html).\n\n## License\n\nCopyright © 2010–2022 [Casebook PBC](https://www.casebook.net).\nLicensed under the MIT license, see [LICENSE](/LICENSE) file.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcasecommons%2Fwith_model","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcasecommons%2Fwith_model","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcasecommons%2Fwith_model/lists"}