Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
A

active_type

> 编程语言
Open source

Make any Ruby object quack like ActiveRecord

1.1K stars0 likes1 views
WebsiteGitHub

About

Make any Ruby object quack like ActiveRecord

Make any Ruby object quack like ActiveRecord

ActiveType is our take on "presenter models" (or "form models") in Rails. We want to have controllers (and forms) talk to models that are either not backed by a database table, or have additional functionality that should not be shared to the rest of the application.

However, we do not want to lose ActiveRecord's amenities, like validations, callbacks, etc.

Examples for use cases are models to support sign in:

ruby
class SignIn  "User (...)"

# or
sign_up = SignUp.new
sign_up.class # => "SignUp (...)"
sign_up.class.extended_record_base_class # => "User (...)"

Inheriting from ActiveType:: objects

If you want to inherit from an ActiveType class, simply do

ruby
class SignUp  "kratob").nickname # "kratob"

Overriding accessors

You can override attribute getters and setters using super:

ruby
class SignIn 
  

    
      

    
  
  • You have to say nests_many :records

  • records will be validated and saved automatically

  • The generated .records_attributes = expects parameters like ActiveRecord's nested attributes, and works together with the fields_for helper:

    • either as a hash (where the keys are meaningless)

      ruby
      {
        '1' => { date: "new record's date" },
        '2' => { id: '3', date: "existing record's date" }
      }
    • or as an array

      ruby
      [
        { date: "new record's date" },
        { id: '3', date: "existing record's date" }
      ]

To use it with single records, use nests_one. It works like accept_nested_attributes does for has_one. Use .record_attributes = to build the child record.

Supported options for nests_many / nests_one are:

  • build_scope

    Used to build new records, for example:

    ruby
    nests_many :documents, build_scope: proc { Document.where(:state => "fresh") }
  • find_scope

    Used to find existing records (in order to update them).

  • scope

    Sets find_scope and build_scope together.

    If you don't supply a scope, ActiveType will guess from the association name, i.e. saying

    ruby
    nests_many :documents

    is the same as saying

    ruby
    nests_many :documents, scope: proc { Document }

    which is identical to

    ruby
    nests_many :documents, build_scope: proc { Document }, find_scope: proc { Document }

    All ...scope options are evaled in the context of the record on first use, and cached.

  • allow_destroy

    Allow to destroy records if the attributes contain _destroy => '1'

  • reject_if

    Pass either a proc of the form proc { |attributes| ... }, or a symbol indicating a method, or :all_blank.

    Will reject attributes for which the proc or the method returns true, or with only blank values (for :all_blank).

  • default

    Initializes the association on first access with the given proc:

    ruby
    nests_many :documents, default: proc { Documents.all }

Options supported exclusively by nests_many are:

  • index_errors

    Use a boolean to get indexed errors on related records. In Rails 5 you can make it global with config.active_record.index_nested_attribute_errors = true.

Casting records or relations

When working with ActiveType you will often find it useful to cast an ActiveRecord instance to its extended ActiveType::Record variant.

Use ActiveType.cast for this:

ruby
class User  true

This is basically like ActiveRecord#becomes, but with less bugs and more consistent behavior.

Note that cast is destructive. The originally casted record (user) and the returned record (sign_up) share internal state (such as attributes). To avoid unexpected behavior, the original record will raise an error when trying to change or persist it. Also, casting of a record that has changes in its loaded associations is prevented, because those changes would be lost. If you know what you are doing and absolutely want that, you may use the option force: true to allow this potentially problematic behaviour, e.g. sign_up = ActiveType.cast(user, SignUp, force: true)

You can also cast an entire relation (scope) to a relation of an ActiveType::Record:

ruby
adult_users = User.where('age >= 18')
adult_sign_ups = ActiveType.cast(adult_users, SignUp)
sign_up = adult_sign_ups.find(1)
sign_up.is_a?(SignUp) # => true

If you need to add some special logic after casting you can add an after_cast method:

ruby
class SignUp  bundle exec rspec spec`.
- When you make a pull request, tests are automatically run against all variants and Rubies on travis.ci.

If you would like to contribute:

- Fork the repository.
- Push your changes **with passing specs**.
- Send us a pull request.

I'm very eager to keep this gem lightweight and on topic. If you're unsure whether a change would make it into the gem, [talk to me beforehand](mailto:[email protected]).

Credits
-------

Tobias Kraze from [makandra](http://makandra.com/)

Henning Koch from [makandra](http://makandra.com/)

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Ruby

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言