Class: Flareshow::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/base.rb

Overview

the base class for Flareshow can be inherited from to create Shareflow resource classes or the class methods can be used to interact with the API directly

Direct Known Subclasses

Comment, FileAttachment, Flow, Invitation, Membership, Post, User

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(data = {}, source = :client) ⇒ Base

constructor build a new Flareshow::Base resource



233
234
235
236
237
# File 'lib/base.rb', line 233

def initialize(data={}, source = :client)
  @data = {}
  data["id"] = UUID.generate.upcase if source == :client
  update(data, source)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object

fallback to getter or setter



326
327
328
329
# File 'lib/base.rb', line 326

def method_missing(meth, *args)
  meth = meth.to_s
  meth.match(/\=/) ? set(meth.gsub(/\=/,''), *args) : get(meth)
end

Class Attribute Details

.serverObject

Returns the value of attribute server.



28
29
30
# File 'lib/base.rb', line 28

def server
  @server
end

Class Method Details

.allObject

get all the resources of this type from the server



194
195
196
197
198
# File 'lib/base.rb', line 194

def all
  key = Flareshow::ClassToResourceMap[self.name]
  params = DEFAULT_PARAMS
  self.query({key => params})
end

.api_endpointObject

return the api endpoint for a given host and domain



36
37
38
# File 'lib/base.rb', line 36

def api_endpoint
  "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/api/v2.json"
end

.assimilate_resources(response) ⇒ Object

assimilate the resources provided in the response



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/base.rb', line 147

def assimilate_resources(response)
  results = {}
  # process each resource key and generate a new object
  # or merge the object data with an existing object
  response[:body].each do |resource_pair|
    resource_key, resources = resource_pair[0], resource_pair[1]
    klass = Kernel.const_get(Flareshow::ResourceToClassMap[resource_key])
    next unless klass
    resources.each do |resource_data|
      item = klass.get(resource_data["id"], :server)
      item.update(resource_data, :server)
      results[resource_key] ||= []
      results[resource_key].push(item)
    end
  end
  results
end

.auth_endpointObject

return the authentication endpoint for a given host and domain



31
32
33
# File 'lib/base.rb', line 31

def auth_endpoint
  "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/api/v2/auth.json"
end

.authenticate(params = {}, callbacks = {}) ⇒ Object

authenticate with the server



75
76
77
78
79
80
81
82
# File 'lib/base.rb', line 75

def authenticate(params={}, callbacks={})
  params = [
    Curl::PostField.content("login", params[:login]),
    Curl::PostField.content("password", params[:password])
  ]
  response = post(auth_endpoint, params)
  handle_response(response, callbacks)
end

.commit(params = {}, callbacks = {}, files = []) ⇒ Object

commit changes to the server



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/base.rb', line 100

def commit(params={}, callbacks={}, files=[])
  curl_params = []
  has_files = false
  if params["posts"]
    # add any file parts passed in and assign a part id to the 
    params["posts"] = (params["posts"]).map do |f|
      if f["files"]
        f["files"] = (f["files"]).each do |ff|
          has_files = true
          curl_params.push(Curl::PostField.file(ff["part_id"], ff["file_path"]))
        end
      end
      f
    end
  end
  
  params["files"] = []
  
  # add the json request parts
  curl_params += [
    Curl::PostField.content("key", User.current.get("auth_token"), 'application/json'),
    Curl::PostField.content("data", params.to_json, 'application/json')
  ]
  
  response = post(api_endpoint, curl_params)
  results = assimilate_resources(response) if response[:status_code] == 200
  handle_response(response,callbacks,results)
end

.create(params) ⇒ Object

create a resource local and sync it to the server



217
218
219
# File 'lib/base.rb', line 217

def create(params)
  new(params).save
end

.dispatch(response, callbacks = {}) ⇒ Object

dispatch a request to the appropriate callback



166
167
168
169
170
171
172
173
# File 'lib/base.rb', line 166

def dispatch(response, callbacks={})
  case response[:status_code]
  when 200...201
    callbacks[:on_success].call(response[:body]) if callbacks[:on_success]
  else
    callbacks[:on_failure].call(response[:body]) if callbacks[:on_failure]
  end
end

.find(params) ⇒ Object

find a resource by querying the server



201
202
203
204
205
# File 'lib/base.rb', line 201

def find(params)
  key = Flareshow::ClassToResourceMap[self.name]
  params = DEFAULT_PARAMS.merge(params)
  (self.query({key => params}) || {})[key]
end

.firstObject

return the first resource in the client store or go to the server and fetch one item



209
210
211
212
213
# File 'lib/base.rb', line 209

def first
  return store.first if store.size > 0
  find({:limit => 1})
  return store.first
end

.get(id_or_object, source = :client) ⇒ Object

find an existing instance of this object in the client or create a new one



176
177
178
179
180
181
182
183
184
# File 'lib/base.rb', line 176

def get(id_or_object, source = :client)
  o = if id_or_object.is_a?(String) || id_or_object.is_a?(Integer)
    id = id_or_object.to_s
    store[id] ||= new({"id" => id}, source)
  elsif
    id = id_or_object["id"]
    store[id] ||= new(id_or_object, source)
  end
end

.handle_response(response, callbacks = {}, results = nil) ⇒ Object

return the results directly or invoke callbacks if provided



130
131
132
133
134
135
136
137
# File 'lib/base.rb', line 130

def handle_response(response, callbacks={}, results=nil)
  if callbacks.empty?
    results
  else
    dispatch(response, callbacks)
    true
  end
end

.http_get(url) ⇒ Object

do a get request



64
65
66
67
68
69
70
71
72
# File 'lib/base.rb', line 64

def http_get(url)
  request = Curl::Easy.new(url + "?key=#{User.current.get("auth_token")}") do |curl|
    curl.headers = {
      'User-Agent'    => 'flareshow 0.1'
    }
  end
  request.perform()
  request.body_str
end

.listObject

list out the instances in memory



187
188
189
190
191
# File 'lib/base.rb', line 187

def list
  store.each_value do |v|
    Util.log_info(v.inspect)
  end
end

.post(url, params) ⇒ Object

make a post request to an endpoint returns a hash of

- status code
- headers
- body


50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/base.rb', line 50

def post(url, params)
  raise ConfigurationException unless server_defined?
  request = Curl::Easy.new(url) do |curl|
    curl.headers = {
      'Accept'        => 'application/json',
      'User-Agent'    => 'flareshow 0.1'
    }
    curl.multipart_form_post=true
  end
  request.http_post(*params)
  process_response(request)
end

.process_response(request) ⇒ Object

get the interesting bits out of the curl response



140
141
142
143
144
# File 'lib/base.rb', line 140

def process_response(request)
  response = {:status_code => request.response_code, :headers => request.header_str, :body => JSON.parse(request.body_str)}
  Util.log_info JSON.pretty_generate(response)
  response
end

.query(params = {}, callbacks = {}) ⇒ Object

query the server



85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/base.rb', line 85

def query(params={}, callbacks={})
  raise UserRequiredException unless User.current

  # add the json request parts
  params = [
    Curl::PostField.content("key", User.current.get("auth_token"), 'application/json'),
    Curl::PostField.content("query", params.to_json, 'application/json')
  ]
  
  response = post(api_endpoint, params)
  results = assimilate_resources(response) if response[:status_code] == 200
  handle_response(response,callbacks,results)
end

.server_defined?Boolean

has the server been configured?

Returns:

  • (Boolean)


41
42
43
# File 'lib/base.rb', line 41

def server_defined?
  !!Flareshow::Base.server
end

.storeObject



221
222
223
# File 'lib/base.rb', line 221

def store
  @objects ||= Dictionary.new
end

Instance Method Details

#changesObject

all the state that has been modified on the client



315
316
317
318
319
320
321
322
323
# File 'lib/base.rb', line 315

def changes
  attributes = @data.inject({}) do |memo, pair|
    key, value = *pair
    if @data[key] != @data["original_#{key}"] && !key.to_s.match(/original/)
      memo[key] = value
    end
    memo
  end
end

#destroy(callbacks = {}) ⇒ Object

destroy the resource on the server



259
260
261
262
263
264
# File 'lib/base.rb', line 259

def destroy(callbacks={})
  key = Flareshow::ClassToResourceMap[self.class.name]
  self.class.commit({key => [{"id" => id, "_removed" => true}]}, callbacks)
  mark_destroyed!
  self
end

#destroyed?Boolean

has this resource been destroyed

Returns:

  • (Boolean)


267
268
269
# File 'lib/base.rb', line 267

def destroyed?
  self._removed || self.frozen?
end

#get(key) ⇒ Object

get a data value



310
311
312
# File 'lib/base.rb', line 310

def get(key)
  @data[key]
end

#idObject

return the server id of a resource



286
287
288
# File 'lib/base.rb', line 286

def id
  @data["id"]
end

#method_nameObject

has this model been removed on the server



332
333
334
# File 'lib/base.rb', line 332

def method_name
  !!self._removed
end

#refresh(callbacks = {}) ⇒ Object

reload the resource from the server



244
245
246
247
248
249
# File 'lib/base.rb', line 244

def refresh(callbacks={})
  key = Flareshow::ClassToResourceMap[self.class.name]
  results = self.class.query({key => {"id" => id}}, callbacks)
  mark_destroyed! if results.empty?
  self
end

#save(callbacks = {}) ⇒ Object

save a resource to the server



252
253
254
255
256
# File 'lib/base.rb', line 252

def save(callbacks={})
  key = Flareshow::ClassToResourceMap[self.class.name]
  self.class.commit({key => [(self.changes || {}).merge({"id" => id})] }, callbacks)
  self
end

#set(key, value, source = :client) ⇒ Object

keep track of dirty state on the client by maintaining a copy of the original state of each intstance variable when it is provided by the server



303
304
305
306
307
# File 'lib/base.rb', line 303

def set(key, value, source = :client)
  # Util.log_info("setting #{key} : #{value}")
  @data["original_#{key}"] = value if source == :server
  @data[key.to_s]=value
end

#update(attributes, source = :client) ⇒ Object

update the instance data for this resource keeping track of dirty state if the update came from the client



293
294
295
296
297
298
# File 'lib/base.rb', line 293

def update(attributes, source = :client)
  attributes.each do |p|
    key, value = p[0], p[1]
    self.set(key, value, source)
  end
end