vector<t_field*>::const_iterator m_iter;
if (members.size() > 0) {
- indent(out) << "attr_accessor ";
+ indent(out) << "Thrift::Struct.field_accessor self";
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
- if (m_iter != members.begin()) {
- out << ", ";
- }
- out << ":" << (*m_iter)->get_name();
+ out << ", :" << (*m_iter)->get_name();
}
out << endl;
}
class Fibonacci_args
include Thrift::Struct
- attr_accessor :n
+ Thrift::Struct.field_accessor self, :n
FIELDS = {
1 => {:type => Thrift::Types::BYTE, :name => 'n'}
}
class Fibonacci_result
include Thrift::Struct
- attr_accessor :success
+ Thrift::Struct.field_accessor self, :success
FIELDS = {
0 => {:type => Thrift::Types::I32, :name => 'success'}
}
+require 'thrift/types'
require 'set'
module Thrift
module Struct
def initialize(d={})
each_field do |fid, type, name, default|
- instance_variable_set("@#{name}", d.fetch(name.to_s) { d.fetch(name.to_sym) { default.dup rescue default } })
+ value = d.delete(name.to_s) { d.delete(name.to_sym) { default.dup rescue default } }
+ Thrift.check_type(value, type)
+ instance_variable_set("@#{name}", value)
end
+ raise Exception, "Unknown arguments given to #{self.class}.new" unless d.empty?
end
def struct_fields
true
end
+ def self.field_accessor(klass, *fields)
+ fields.each do |field|
+ klass.send :attr_reader, field
+ klass.send :define_method, "#{field}=" do |value|
+ Thrift.check_type(value, klass::FIELDS.values.find { |f| f[:name].to_s == field.to_s }[:type] )
+ instance_variable_set("@#{field}", value)
+ end
+ end
+ end
+
protected
def handle_message(iprot, fid, ftype)
class Greeting_args
include Thrift::Struct
- attr_accessor :english
+ Thrift::Struct.field_accessor self, :english
FIELDS = {
1 => {:type => Thrift::Types::BOOL, :name => 'english'}
}
class Greeting_result
include Thrift::Struct
- attr_accessor :success
+ Thrift::Struct.field_accessor self, :success
FIELDS = {
0 => {:type => Thrift::Types::STRUCT, :name => 'success', :class => Hello}
}
class Block_result
include Thrift::Struct
- attr_accessor :success
+ Thrift::Struct.field_accessor self, :success
FIELDS = {
0 => {:type => Thrift::Types::BOOL, :name => 'success'}
}
class Sleep_args
include Thrift::Struct
- attr_accessor :seconds
+ Thrift::Struct.field_accessor self, :seconds
FIELDS = {
1 => {:type => Thrift::Types::DOUBLE, :name => 'seconds'}
}
module SpecNamespace
class Hello
include Thrift::Struct
- attr_accessor :greeting
+ Thrift::Struct.field_accessor self, :greeting
FIELDS = {
1 => {:type => Thrift::Types::STRING, :name => 'greeting', :default => 'hello world'}
}
class Foo
include Thrift::Struct
- attr_accessor :simple, :words, :hello, :ints, :complex, :shorts
+ Thrift::Struct.field_accessor self, :simple, :words, :hello, :ints, :complex, :shorts
FIELDS = {
1 => {:type => Thrift::Types::I32, :name => 'simple', :default => 53},
2 => {:type => Thrift::Types::STRING, :name => 'words', :default => 'words'},
class BoolStruct
include Thrift::Struct
- attr_accessor :yesno
+ Thrift::Struct.field_accessor self, :yesno
FIELDS = {
1 => {:type => Thrift::Types::BOOL, :name => 'yesno', :default => true}
}
struct = Foo.new
lambda { struct.send :write_container, nil, nil, {:type => "foo"} }.should raise_error(StandardError, "Not a container type: foo")
end
+
+ it "should support optional type-checking in Thrift::Struct.new" do
+ Thrift.type_checking = true
+ begin
+ lambda { Hello.new(:greeting => 3) }.should raise_error(TypeError, "Expected Types::STRING, received Fixnum")
+ ensure
+ Thrift.type_checking = false
+ end
+ lambda { Hello.new(:greeting => 3) }.should_not raise_error(TypeError)
+ end
+
+ it "should support optional type-checking in field accessors" do
+ Thrift.type_checking = true
+ begin
+ hello = Hello.new
+ lambda { hello.greeting = 3 }.should raise_error(TypeError, "Expected Types::STRING, received Fixnum")
+ ensure
+ Thrift.type_checking = false
+ end
+ lambda { hello.greeting = 3 }.should_not raise_error(TypeError)
+ end
+
+ it "should raise an exception when unknown types are given to Thrift::Struct.new" do
+ lambda { Hello.new(:fish => 'salmon') }.should raise_error(Exception, "Unknown arguments given to SpecNamespace::Hello.new")
+ end
end
end