Class: Dimelo::CCP::API::Model

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Naming, ActiveModel::Translation
Includes:
ActiveModel::Validations
Defined in:
lib/dimelo/ccp/api/model.rb

Constant Summary collapse

INTERPOLATION_PATTERN =
/%\{(\w+)\}/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hash = {}, client = nil) ⇒ Model

Returns a new instance of Model.



108
109
110
111
112
113
114
115
# File 'lib/dimelo/ccp/api/model.rb', line 108

def initialize(hash={}, client=nil)
  @errors = ActiveModel::Errors.new(self)
  @tracked_attributes = []
  self.client = client
  hash.each do |k,v|
    self.send("#{k}=", v) if self.respond_to?("#{k}=")
  end
end

Instance Attribute Details

#clientObject

Returns the value of attribute client.



103
104
105
# File 'lib/dimelo/ccp/api/model.rb', line 103

def client
  @client
end

#errorsObject

Returns the value of attribute errors.



104
105
106
# File 'lib/dimelo/ccp/api/model.rb', line 104

def errors
  @errors
end

#tracked_attributesObject (readonly)

Returns the value of attribute tracked_attributes.



104
105
106
# File 'lib/dimelo/ccp/api/model.rb', line 104

def tracked_attributes
  @tracked_attributes
end

Class Method Details

.attribute(arg) ⇒ Object



17
18
19
20
21
22
23
24
25
26
# File 'lib/dimelo/ccp/api/model.rb', line 17

def attribute(arg)
  @attributes ||= []
  @attributes << arg
  attr_reader(arg)
  class_eval "
  def #{arg}=(val)
    @tracked_attributes << :#{arg}
    @#{arg} = val
  end"
end

.attributes(*args) ⇒ Object



28
29
30
31
32
33
# File 'lib/dimelo/ccp/api/model.rb', line 28

def attributes(*args)
  args.each do |arg|
    attribute arg
  end
  @attributes
end

.belongs_to(association, options = {}) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/dimelo/ccp/api/model.rb', line 63

def belongs_to(association, options={})
  attr_writer association
  foreign_class = options[:class_name] || "#{name.gsub(/(\w+)$/, '')}#{association.to_s.camelize}"
  foreign_reference = self.name.demodulize.underscore
  foreign_key = "#{association}_id"

  class_eval <<-EOS, __FILE__, __LINE__ + 1

    def #{association}(client=nil)
      client ||= @client
      @#{association} ||= #{foreign_class}.find(self.#{foreign_key}, client)
    end

  EOS
end

.compute_path(criterias = {}) ⇒ Object



95
96
97
98
99
# File 'lib/dimelo/ccp/api/model.rb', line 95

def compute_path(criterias={})
  path.gsub(INTERPOLATION_PATTERN) do |match|
    criterias.delete($1.to_sym) || ''
  end.chomp '/'
end

.find(*args) ⇒ Object



79
80
81
82
83
84
85
86
# File 'lib/dimelo/ccp/api/model.rb', line 79

def find(*args)
  client = args.pop
  criterias = args.pop
  criterias = {:id => criterias} unless criterias.is_a?(Hash)
  Dimelo::CCP::API::LazzyCollection.new(criterias) do |criterias|
    parse(client.transport(:get, compute_path(criterias), criterias), client)
  end
end

.has_many(association, options = {}) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/dimelo/ccp/api/model.rb', line 40

def has_many(association, options={})
  foreign_class = options[:class_name] || "#{name.gsub(/(\w+)$/, '')}#{association.to_s.singularize.camelize}"
  foreign_reference = self.name.demodulize.underscore
  foreign_key = "#{foreign_reference}_id"

  class_eval <<-EOS, __FILE__, __LINE__ + 1

    def #{association}(client=nil)
      # FIXME: clear cache if client change, or something like that
      client ||= @client
      @#{association} ||= #{foreign_class}.find({:#{foreign_key} => self.id}, client).each do |instance|
        instance.#{foreign_reference} = self
      end
    end

    def #{association}=(items)
      @#{association} = items.each{ |i| i.#{foreign_reference} = self }
    end

  EOS

end

.parse(document, client = nil) ⇒ Object



88
89
90
91
# File 'lib/dimelo/ccp/api/model.rb', line 88

def parse(document, client=nil)
  object = Dimelo::CCP::API.decode_json(document)
  object.is_a?(Array) ? object.map{ |i| new(i, client) } : new(object, client)
end

.path(*args) ⇒ Object



12
13
14
15
# File 'lib/dimelo/ccp/api/model.rb', line 12

def path(*args)
  @path = args.first if args.any?
  @path ||= "#{name.demodulize.pluralize.underscore}/%{id}"
end

.submit_attributes(*args) ⇒ Object



35
36
37
38
# File 'lib/dimelo/ccp/api/model.rb', line 35

def submit_attributes(*args)
  @submit_attributes = args if args.any?
  @submit_attributes ||= []
end

Instance Method Details

#==(other) ⇒ Object



191
192
193
# File 'lib/dimelo/ccp/api/model.rb', line 191

def ==(other)
  other.is_a?(self.class) and self.id == other.id and self.id.present?
end

#attributesObject



125
126
127
# File 'lib/dimelo/ccp/api/model.rb', line 125

def attributes
  Hash[self.class.attributes.map{ |key| [key, self.send(key)] }]
end

#attributes=(hash) ⇒ Object



129
130
131
132
133
134
135
136
137
# File 'lib/dimelo/ccp/api/model.rb', line 129

def attributes=(hash)
  hash.each do |k, value|
    if self.respond_to? "#{k}="
      self.send("#{k}=", value)
    else
      warn("Unknown field or method #{k} for object #{self.inspect}")
    end
  end
end

#createObject



159
160
161
162
163
164
165
# File 'lib/dimelo/ccp/api/model.rb', line 159

def create
  attrs = submit_attributes
  path = compute_path(attrs)
  response = client.transport(:post, path, attrs)
  self.attributes = Dimelo::CCP::API.decode_json(response)
  id.present?
end

#destroyObject



179
180
181
182
# File 'lib/dimelo/ccp/api/model.rb', line 179

def destroy
  client.transport(:delete, compute_path(self.attributes))
  freeze
end

#merge!(other) ⇒ Object



195
196
197
# File 'lib/dimelo/ccp/api/model.rb', line 195

def merge!(other)
  self.attributes = other.attributes
end

#new_record?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'lib/dimelo/ccp/api/model.rb', line 147

def new_record?
  id.blank?
end

#reloadObject

Raises:

  • (ArgumentError)


184
185
186
187
188
189
# File 'lib/dimelo/ccp/api/model.rb', line 184

def reload
  raise ArgumentError.new("You cannot fetch models without a populated id attribute") if id.nil?
  other = self.class.find(id, client)
  self.attributes.merge!(other.attributes) if other
  self
end

#saveObject



151
152
153
154
155
156
157
# File 'lib/dimelo/ccp/api/model.rb', line 151

def save
  if new_record?
    create
  else
    update
  end
end

#submit_attributesObject



143
144
145
# File 'lib/dimelo/ccp/api/model.rb', line 143

def submit_attributes
  Hash[tracked_submit_attributes.map{ |key| [key, self.send(key)] }]
end

#to_jsonObject



199
200
201
# File 'lib/dimelo/ccp/api/model.rb', line 199

def to_json
  Dimelo::CCP::API.encode_json(self.attributes)
end

#tracked_submit_attributesObject



139
140
141
# File 'lib/dimelo/ccp/api/model.rb', line 139

def tracked_submit_attributes
  @tracked_attributes & self.class.submit_attributes
end

#updateObject



167
168
169
170
171
172
173
# File 'lib/dimelo/ccp/api/model.rb', line 167

def update
  attrs = submit_attributes
  path = compute_path(attributes)
  response = client.transport(:put, path, attrs)
  self.attributes = Dimelo::CCP::API.decode_json(response)
  errors.empty?
end

#valid?Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/dimelo/ccp/api/model.rb', line 175

def valid?
  true
end

#warn(message) ⇒ Object



203
204
205
# File 'lib/dimelo/ccp/api/model.rb', line 203

def warn(message)
  defined?(Rails) ? Rails.logger.warn(message) : STDERR.puts(message)
end