aboutsummaryrefslogtreecommitdiffstats
path: root/actionwebservice/lib/action_web_service/struct.rb
blob: d065dae03b9a0b490810ebf66c4f1522b144c93c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
module ActionWebService
  # To send structured types across the wire, derive from ActionWebService::Struct,
  # and use +member+ to declare structure members.
  #
  # ActionWebService::Struct should be used in method signatures when you want to accept or return
  # structured types that have no Active Record model class representations, or you don't
  # want to expose your entire Active Record model to remote callers.
  #
  # === Example
  #
  #   class Person < ActionWebService::Struct
  #     member :id,         :int
  #     member :firstnames, [:string]
  #     member :lastname,   :string
  #     member :email,      :string
  #   end
  #   person = Person.new(:id => 5, :firstname => 'john', :lastname => 'doe')
  #
  # Active Record model classes are already implicitly supported in method
  # signatures.
  class Struct
    # Action WebService Struct subclasses should be reloaded by the dispatcher in Rails
    # when Dependencies.mechanism = :load.
    include Reloadable::Subclasses
    
    # If a Hash is given as argument to an ActionWebService::Struct constructor,
    # it can contain initial values for the structure member.
    def initialize(values={})
      if values.is_a?(Hash)
        values.map{|k,v| __send__('%s=' % k.to_s, v)}
      end
    end

    # The member with the given name
    def [](name)
      send(name.to_s)
    end

    # Iterates through each member
    def each_pair(&block)
      self.class.members.each do |name, type|
        yield name, self.__send__(name)
      end
    end

    class << self
      # Creates a structure member with the specified +name+ and +type+. Generates
      # accessor methods for reading and writing the member value.
      def member(name, type)
        name = name.to_sym
        type = ActionWebService::SignatureTypes.canonical_signature_entry({ name => type }, 0)
        write_inheritable_hash("struct_members", name => type)
        class_eval <<-END
          def #{name}; @#{name}; end
          def #{name}=(value); @#{name} = value; end
        END
      end
  
      def members # :nodoc:
        read_inheritable_attribute("struct_members") || {}
      end

      def member_type(name) # :nodoc:
        members[name.to_sym]
      end
    end
  end
end