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
54 changes: 23 additions & 31 deletions lib/simple_form_object.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "simple_form_object/version"
require "simple_form_object/attribute"
require "active_model"
require "active_support"

Expand All @@ -14,16 +15,34 @@ def attribute(name, type = :string, options = {})
_attributes << Attribute.new(name, type, options)
end

def route_as(model_name)
@model_name = model_name.to_s.camelize
end

def _attributes
@_attributes ||= []
inherited_attributes = []

ancestors.drop(1).each do |ancestor|
if ancestor.respond_to?(:_attributes)
inherited_attributes.concat(ancestor._attributes)
end
end

@_attributes ||= inherited_attributes
end

def _attribute(attribute_name)
_attributes.select{|a| a.name == attribute_name}.first
end

def model_name
ActiveModel::Name.new(self, nil, self.to_s.gsub(/Form$/, ''))
ActiveModel::Name.new(self, nil, model_name_for_routing)
end

private

def model_name_for_routing
@model_name || to_s.gsub(/Form$/, "")
end
end

Expand All @@ -46,34 +65,7 @@ def attributes
attribs
end

class Attribute
def initialize(name, type = nil, options)
@name = name
@type = type || :string
@options = options

extract_options
end

attr_accessor :name, :type, :options

def fake_column
self
end

def apply_default_to(form)
if form.send(@name).nil?
form.send("#{@name}=", @default) if @apply_default
end
end

private

def extract_options
@apply_default = true
@default = options.fetch(:default) { @apply_default = false; nil }
@skip_validations = options.fetch(:skip_validations, false)
end
def has_attribute?(attribute)
attributes.key?(attribute)
end

end
40 changes: 40 additions & 0 deletions lib/simple_form_object/attribute.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
module SimpleFormObject
class Attribute
def initialize(name, type = nil, options)
@name = name
@type = type || :string
@options = options

extract_options
end

attr_accessor :name, :type, :options

def fake_column
self
end

def apply_default_to(form)
if form.send(@name).nil?
default_value = @default.respond_to?(:call) ? @default.call : @default
form.send("#{@name}=", default_value) if @apply_default
end
end

def number?
%i(integer float decimal).include?(type)
end

def limit
nil
end

private

def extract_options
@apply_default = true
@default = options.fetch(:default) { @apply_default = false; nil }
@skip_validations = options.fetch(:skip_validations, false)
end
end
end
41 changes: 41 additions & 0 deletions spec/attribute_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,47 @@
expect(form.foo).to eq false
end
end
end

describe '#limit' do
subject(:attribute) { SimpleFormObject::Attribute.new(:name, :string, {}) }

it 'returns nil' do
expect(subject.limit).to be_nil
end
end

describe '#number?' do
context 'when attribute is an integer' do
subject(:attribute) { SimpleFormObject::Attribute.new(:name, :integer, {}) }

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

context 'when attribute is a float' do
subject(:attribute) { SimpleFormObject::Attribute.new(:name, :float, {}) }

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

context 'when attribute is a decimal' do
subject(:attribute) { SimpleFormObject::Attribute.new(:name, :decimal, {}) }

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

context 'when attribute is a string' do
subject(:attribute) { SimpleFormObject::Attribute.new(:name, :string, {}) }

it 'returns false' do
expect(subject).not_to be_number
end
end
end
end
52 changes: 44 additions & 8 deletions spec/model_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,20 +67,56 @@
end

describe '.model_name' do
let(:klass) do
class KlassForm
include SimpleFormObject
context 'by convention' do
let(:klass) do
class KlassForm
include SimpleFormObject
end

KlassForm
end

it 'should return an ActiveModel::Name' do
expect(klass.model_name).to be_a_kind_of ActiveModel::Name
end

it 'should remove Form from the name of the class' do
expect(klass.model_name.name).to eq 'Klass'
end
end

context 'by declaration' do
let(:klass) do
class KlassForm
include SimpleFormObject

route_as :custom
end

KlassForm
end

it 'should return an ActiveModel::Name' do
expect(klass.model_name).to be_a_kind_of ActiveModel::Name
end

it 'should remove Form from the name of the class' do
expect(klass.model_name.name).to eq 'Custom'
end
end
end

KlassForm
describe '#has_attribute?' do
before do
klass.attribute :foo
end

it 'should return an ActiveModel::Name' do
expect(klass.model_name).to be_a_kind_of ActiveModel::Name
it 'returns true for a declared attribute' do
expect(instance.has_attribute?(:foo)).to be(true)
end

it 'should remove Form from the name of the class' do
expect(klass.model_name.name).to eq "Klass"
it 'returns false for a declared attribute' do
expect(instance.has_attribute?(:bar)).to be(false)
end
end
end