Skip to content

Schema #11

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

Merged
merged 9 commits into from
Aug 26, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
implement schemable
  • Loading branch information
Jeff Ching committed Aug 25, 2014
commit e51e204f3d8eca871a3d353299a3be704e6da1a1
73 changes: 69 additions & 4 deletions lib/json_api_client/helpers/schemable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,58 @@ module Helpers
module Schemable
extend ActiveSupport::Concern

Field = Struct.new(:name, :type, :default)
Field = Struct.new(:name, :type, :default) do
def cast(value)
return nil if value.nil?

case type
when :integer
value.to_i
when :string
value.to_s
when :float
value.to_f
when :boolean
!!value
end
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if field should be a separate class but I cant think of any cases where its not more than a Struct

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was keeping it within the Schemable namespace because you won't be creating one of these outside of this context.


included do
class_attribute :schema
self.schema = []
initializer do |obj, params|
obj.send(:set_default_values)
end
end

class Schema
def initialize
@fields = {}
end

def add(field)
@fields[field.name.to_sym] = field
end

def size
@fields.size
end

def each_property(&block)
@fields.values.each(&block)
end

def [](property_name)
@fields[property_name.to_sym]
end
end

module ClassMethods
def property(name, options = {})
def schema
@schema ||= Schema.new
end

def property(name, options = {})
schema.add(Field.new(name, options[:type], options[:default]))
end

def properties(*names)
Expand All @@ -22,6 +64,29 @@ def properties(*names)
end
end
end

protected

def set_attribute(name, value)
property = property_for(name)
value = property.cast(value) if property
super(name, value)
end

def has_attribute?(attr_name)
!!self.class.schema[attr_name] || super
end

def set_default_values
self.class.schema.each_property do |property|
attributes[property.name] = property.default unless attributes.has_key?(property.name)
end
end

def property_for(name)
self.class.schema[name]
end

end
end
end
4 changes: 2 additions & 2 deletions test/unit/schemable_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def test_defines_fields
resource = SchemaResource.new

%w(a b c d).each do |method_name|
assert resource.respond_to?(method_name)
assert resource.respond_to?("#{method_name}=")
assert resource.respond_to?(method_name), "should respond_to?(:#{method_name})"
assert resource.respond_to?("#{method_name}="), "should respond_to?(:#{method_name}=)"
end

assert_equal 4, SchemaResource.schema.size
Expand Down