Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#after_cast #185

Merged
merged 5 commits into from
Dec 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to this project will be documented in this file.

## 2.4.0 (2023-12-22)
* Added: You can implement an `#after_cast` that is called with the original record when calling `ActiveType.cast`.
Thanks to @MaximilianoGarciaRoe.

## 2.3.4 (2023-05-11)

* Fixed: ActiveType.cast preserves `.strict_loading?` and `.readonly?`
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.5.2.mysql2.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.5.2.pg.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.5.2.sqlite3.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.6.0.sqlite3.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.6.1.pg.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.6.1.sqlite3.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.7.0.pg.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
2 changes: 1 addition & 1 deletion Gemfile.7.0.sqlite3.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
active_type (2.3.4)
active_type (2.4.0)
activerecord (>= 3.2)

GEM
Expand Down
34 changes: 22 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ Examples for use cases are models to support sign in:
class SignIn < ActiveType::Object

# this is not backed by a db table

attribute :username, :string
attribute :password, :string

validates :username, presence: true
validates :password, presence: true

# ...

end
Expand All @@ -38,15 +38,15 @@ class SignUp < ActiveType::Record[User]
# this inherits from User

validates :password, confirmation: true

after_create :send_confirmation_email

def send_confirmation_email
# this should happen on sign-up, but not when creating a user in tests etc.
end

# ...

end
```

Expand Down Expand Up @@ -86,12 +86,12 @@ You can define "columns" by saying `attribute`:

```ruby
class SignIn < ActiveType::Object

attribute :email, :string
attribute :date_of_birth, :date
attribute :accepted_terms, :boolean
attribute :account_type

end
```

Expand All @@ -103,7 +103,7 @@ sign_in.date_of_birth.class # Date
sign_in.accepted_terms? # true
```

ActiveType knows all the types that are allowed in migrations (i.e. `:string`, `:integer`, `:float`, `:decimal`, `:datetime`, `:time`, `:date`, `:boolean`). You can also skip the type to have a virtual attribute without typecasting.
ActiveType knows all the types that are allowed in migrations (i.e. `:string`, `:integer`, `:float`, `:decimal`, `:datetime`, `:time`, `:date`, `:boolean`). You can also skip the type to have a virtual attribute without typecasting.

**`ActiveType::Object` actually inherits from `ActiveRecord::Base`, but simply skips all database access, inspired by [ActiveRecord Tableless](https://github.com/softace/activerecord-tableless).**

Expand Down Expand Up @@ -197,15 +197,15 @@ class SignIn < ActiveType::Object

attribute :email, :string
attribute :nickname, :string

def email
super.downcase
end

def nickname=(value)
super(value.titleize)
end

end
```

Expand Down Expand Up @@ -379,6 +379,16 @@ sign_up.is_a?(SignUp) # => true
```


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

class SignUp < ActiveType::Record[User]
def after_cast(user)
# Called with the original user upon casting.
end
end



Associations
------------

Expand Down
3 changes: 3 additions & 0 deletions lib/active_type/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ def cast_record(record, klass, force: false)

casted[klass.inheritance_column] = klass.sti_name if using_single_table_inheritance

casted.after_cast(record) if casted.respond_to?(:after_cast)

if !force
make_record_unusable(record)
end

casted
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/active_type/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ActiveType
VERSION = '2.3.4'
VERSION = '2.4.0'
end
15 changes: 15 additions & 0 deletions spec/active_type/util_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,17 @@
module UtilSpec

class BaseRecord < ActiveRecord::Base

self.table_name = 'records'
has_many :associated_records

attr_reader :after_cast_called_with

def after_cast(*args)
# will expect this to be called
@after_cast_called_with = args
end

end

class ExtendedRecord < ActiveType::Record[BaseRecord]
Expand Down Expand Up @@ -79,6 +88,12 @@ class AssociatedRecord < ActiveRecord::Base
expect(extended_record.persisted_string).to eq('foo')
end

it 'calls "after_cast" with the original record after casting' do
base_record = UtilSpec::BaseRecord.create!
extended_record = ActiveType::Util.cast(base_record, UtilSpec::BaseRecord)
expect(extended_record.after_cast_called_with).to eq([base_record])
end

context 'casting without copying the @association cache' do
# When casting, the @association_cache is not copied, because of Issues #146, #147 and #148.
# This may be unexpected to a user of Active Type, so we decided to not allow
Expand Down