Skip to content
Open
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
1 change: 0 additions & 1 deletion .ruby-version

This file was deleted.

5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ The `.new` method should be called with the arguments that the form object needs

When initializing a `YAAF` form object, there are two things to keep in mind
1. You need to define the `@models` instance variables to be an array of all the models that you want to be validated/saved within the form object.
2. To leverage `ActiveModel`'s features, you can call `super` to automatically make the attributes be stored in instance variables. If you use it, make sure to also add `attr_accessor`s, otherwise `ActiveModel` will fail.
2. To leverage `ActiveModel`'s features, you can call `super` to automatically make the attributes be stored in instance variables. If you use it, make sure to also add `attribute`s, otherwise `ActiveModel` will fail.

### #valid?

Expand Down Expand Up @@ -254,6 +254,9 @@ Available callbacks are (listed in execution order):

```ruby
class RegistrationForm < YAAF::Form
attribute :email, :string
attribute :name, :string

normalizes :email, with: ->(email) { email.strip.downcase }
normalizes :name, with: ->(name) { name.strip.titleize }

Expand Down
7 changes: 5 additions & 2 deletions docs/recipes/devise.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ For example, a simple registration form will look like this:
# app/forms/registration_form.rb

class RegistrationForm < ApplicationForm
attr_accessor :first_name, :last_name, :email, :password,
:password_confirmation
attribute :first_name, :string
attribute :last_name, :string
attribute :email, :string
attribute :password, :string
attribute :password_confirmation, :string

# To let Devise treat the form object as it were the actual user object
delegate_missing_to :user
Expand Down
5 changes: 3 additions & 2 deletions docs/recipes/json_api.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Using YAAF with nested forms
# Using YAAF with JSON API

When you are using Rails as a JSON API, you can still use `YAAF` to build your models.

Expand Down Expand Up @@ -45,7 +45,8 @@ end
module Api
module V1
class InviteForm < ApplicationForm
attr_accessor :email
attribute :email, :string

validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }

def initialize(args = {})
Expand Down
3 changes: 2 additions & 1 deletion docs/recipes/nested_forms.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ end
# app/forms/invite_form.rb

class InviteForm < ApplicationForm
attr_accessor :email
attribute :email, :string

validates :email, format: { with: URI::MailTo::EMAIL_REGEXP }

def initialize(args = {})
Expand Down
3 changes: 2 additions & 1 deletion docs/recipes/simple_form.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ For example, in a library management system (a pretty minimal one), the form to
# app/forms/book_form.rb

class BookForm < YAAF::Form
attr_accessor :name, :isbn
attribute :name, :string
attribute :isbn, :string

def initialize(attributes)
super(attributes)
Expand Down
2 changes: 1 addition & 1 deletion lib/yaaf/form.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ class Form
include ::ActiveModel::Model
include ::ActiveModel::Validations::Callbacks
include ::ActiveRecord::Transactions
include ::ActiveModel::Attributes

if defined?(::ActiveModel::Attributes::Normalization)
include ::ActiveModel::Attributes
include ::ActiveModel::Attributes::Normalization
end

Expand Down
1 change: 1 addition & 0 deletions spec/support/forms.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
require_relative 'forms/custom_transaction_form'
require_relative 'forms/user_destroy_form'
require_relative 'forms/with_normalize_form'
require_relative 'forms/with_attributes_form'
3 changes: 2 additions & 1 deletion spec/support/forms/multiple_errors_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class MultipleErrorsForm < YAAF::Form
attr_accessor :email, :name
attribute :email, :string
attribute :name, :string

validates :name, format: { with: /[a-zA-Z]+/ }
validates :email, format: { with: /\S+@\S+\.\S+/ }
Expand Down
3 changes: 2 additions & 1 deletion spec/support/forms/registration_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class RegistrationForm < YAAF::Form
attr_accessor :email, :name
attribute :email, :string
attribute :name, :string

validates :name, format: { with: /[a-zA-Z]+/ }, allow_blank: true

Expand Down
3 changes: 2 additions & 1 deletion spec/support/forms/user_destroy_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class UserDestroyForm < YAAF::Form
attr_accessor :email, :name
attribute :email, :string
attribute :name, :string

before_save :mark_user_for_destruction

Expand Down
13 changes: 13 additions & 0 deletions spec/support/forms/with_attributes_form.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class WithAttributesForm < YAAF::Form
attr_accessor :attributes

def initialize(attributes)
@attributes = attributes

@models = [user]
end

def user
@user ||= User.new(attributes)
end
end
5 changes: 4 additions & 1 deletion spec/support/forms/with_commit_callbacks_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class WithCommitCallbacksForm < YAAF::Form
attr_accessor :email, :name, :after_counter
attribute :email, :string
attribute :name, :string

attr_accessor :after_counter

validates :name, format: { with: /[a-zA-Z]+/ }, allow_blank: true
after_commit { @after_counter += 1 }
Expand Down
5 changes: 4 additions & 1 deletion spec/support/forms/with_multiple_callbacks_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class WithMultipleCallbacksForm < YAAF::Form
attr_accessor :email, :name, :result
attribute :email, :string
attribute :name, :string

attr_accessor :result

validates :name, format: { with: /[a-zA-Z]+/ }, allow_blank: true
after_validation :add_to_after_validation_counter, :add_again_to_after_validation_counter
Expand Down
5 changes: 4 additions & 1 deletion spec/support/forms/with_rollback_callbacks_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class WithRollbackCallbacksForm < YAAF::Form
attr_accessor :email, :name, :after_counter
attribute :email, :string
attribute :name, :string

attr_accessor :after_counter

validates :name, format: { with: /[a-zA-Z]+/ }, allow_blank: true
after_rollback { @after_counter += 1 }
Expand Down
5 changes: 4 additions & 1 deletion spec/support/forms/with_save_callbacks_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class WithSaveCallbacksForm < YAAF::Form
attr_accessor :email, :name, :before_counter, :after_counter
attribute :email, :string
attribute :name, :string

attr_accessor :before_counter, :after_counter

validates :name, format: { with: /[a-zA-Z]+/ }, allow_blank: true
before_save :add_to_before_counter
Expand Down
5 changes: 4 additions & 1 deletion spec/support/forms/with_validation_callbacks_form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
class WithValidationCallbacksForm < YAAF::Form
attr_accessor :email, :name, :before_counter, :after_counter
attribute :email, :string
attribute :name, :string

attr_accessor :before_counter, :after_counter

validates :name, format: { with: /[a-zA-Z]+/ }, allow_blank: true
before_validation :add_to_before_counter
Expand Down
76 changes: 76 additions & 0 deletions spec/yaaf/attributes_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# frozen_string_literal: true

RSpec.describe 'Form with attributes' do
let(:options) { {} }
let(:registration_form) { WithAttributesForm.new(attributes) }
let(:attributes) { { email: 'test@example.com', name: 'John' } }

before { expect(registration_form).to be_valid }

describe '#save' do
subject { registration_form.save(options) }

it 'returns true' do
expect(subject).to eq true
end

it 'saves the user' do
expect { subject }.to change { User.count }.by 1
end

it 'saves with correct information' do
expect { subject }.to change {
User.last&.email
}.to('test@example.com').and change {
User.last&.name
}.to('John')
end
end

describe '#save!' do
subject { registration_form.save!(options) }

it 'returns true' do
expect(subject).to eq true
end

it 'saves the user' do
expect { subject }.to change { User.count }.by 1
end

it 'saves with correct information' do
expect { subject }.to change {
User.last&.email
}.to('test@example.com').and change {
User.last&.name
}.to('John')
end
end

describe '#valid?' do
subject { registration_form.valid? }

it { is_expected.to be true }
end

describe '#invalid?' do
subject { registration_form.invalid? }

it { is_expected.to be false }
end

describe '#errors' do
subject do
registration_form.valid?
registration_form.errors
end

it 'returns the correct class' do
expect(subject.class).to eq(ActiveModel::Errors)
end

it 'is empty' do
expect(subject.messages).to be_empty
end
end
end