travis-web/assets/scripts/app/store.coffee
Piotr Sarnacki 46f7e6bba0 Fix remaining ember-data and pusher updates issues
When records are updated by pusher events, we should not mark them as
dirty - we don't modify them on client side anyway.
2013-02-26 04:37:23 +01:00

173 lines
5.4 KiB
CoffeeScript

require 'store/rest_adapter'
coerceId = (id) -> if id == null then null else id+''
Travis.Store = DS.Store.extend
revision: 11
adapter: Travis.RestAdapter.create()
init: ->
@_super.apply this, arguments
@_loadedData = {}
@clientIdToComplete = {}
load: (type, data, prematerialized) ->
result = @_super.apply this, arguments
if result && result.clientId && @clientIdToComplete[result.clientId] == undefined
# I assume that everything that goes through load is complete record
# representation, incomplete hashes from pusher go through merge()
@clientIdToComplete[result.clientId] = true
result
# TODO use isUpdating once we've upgraded ember-data
loadMany: (type, ids, hashes) ->
result = @_super.apply this, arguments
array.set('isLoaded', true) for array in @typeMapFor(type).recordArrays
result
merge: (type, data, incomplete) ->
id = coerceId data.id
typeMap = @typeMapFor(type)
clientId = typeMap.idToCid[id]
record = @recordCache[clientId]
if record
@get('adapter').merge(this, record, data)
else
if (savedData = @clientIdToData[clientId]) && savedData.id?
$.extend(savedData, data)
else
result = @load(type, data, {id: data.id})
if result && result.clientId
clientId = result.clientId
if incomplete
@clientIdToComplete[result.clientId] = false
{ clientId: clientId, id: id }
isInStore: (type, id) ->
!!@typeMapFor(type).idToCid[id]
receive: (event, data) ->
[name, type] = event.split(':')
mappings = @adapter.get('mappings')
type = mappings[name]
if event == 'build:started' && data.build.commit
# TODO: commit should be a sideload record on build, not mixed with it
build = data.build
commit = {
id: build.commit_id
author_email: build.author_email
author_name: build.author_name
branch: build.branch
committed_at: build.committed_at
committer_email: build.committer_email
committer_name: build.committer_name
compare_url: build.compare_url
message: build.message
sha: build.commit
}
delete(data.build.commit)
@loadIncomplete(Travis.Commit, commit)
if event == 'job:log'
data = data.job
job = @find(Travis.Job, data.id)
job.appendLog(number: parseInt(data.number), content: data._log)
else if data[type.singularName()]
@_loadOne(this, type, data)
else if data[type.pluralName()]
@_loadMany(this, type, data)
else
throw "can't load data for #{name}" unless type
_loadOne: (store, type, json) ->
root = type.singularName()
# we get other types of records only in a few situations and
# it's not always needed to update data, so I'm specyfing which
# things I want to update here:
if type == Travis.Build && (json.repository || json.repo)
@loadIncomplete(Travis.Repo, json.repository || json.repo)
result = @loadIncomplete(type, json[root])
if result.id
@find(type, result.id)
addLoadedData: (type, clientId, hash) ->
id = hash.id
@_loadedData[type.toString()] ||= {}
loadedData = (@_loadedData[type][clientId] ||= [])
serializer = @get('adapter.serializer')
Ember.get(type, 'attributes').forEach( (name, meta) ->
value = @extractAttribute(type, hash, name)
if value != undefined
loadedData.pushObject name unless loadedData.contains(name)
, serializer)
Ember.get(type, 'relationshipsByName').forEach( (name, relationship) ->
key = @_keyForBelongsTo(type, relationship.key)
value = @extractBelongsTo(type, hash, key)
if value != undefined
loadedData.pushObject name unless loadedData.contains(name)
, serializer)
isDataLoadedFor: (type, clientId, key) ->
if recordsData = @_loadedData[type.toString()]
if data = recordsData[clientId]
data.contains(key)
loadIncomplete: (type, hash, options) ->
options ?= {}
id = coerceId hash.id
typeMap = @typeMapFor(type)
cidToData = @clientIdToData
clientId = typeMap.idToCid[id]
if clientId && cidToData[clientId] && options.skipIfExists
return
result = @merge(type, hash, true)
if result && result.clientId
@addLoadedData(type, result.clientId, hash)
# TODO: it will be probably needed to uncomment and fix this
#@_updateAssociations(type, type.singularName(), hash)
result
materializeRecord: (type, clientId, id) ->
record = @_super.apply this, arguments
if @clientIdToComplete[clientId] != undefined && !@clientIdToComplete[clientId]
record.set 'incomplete', true
else
record.set 'incomplete', false
record
_loadMany: (store, type, json) ->
root = type.pluralName()
@adapter.sideload(store, type, json, root)
@loadMany(type, json[root])
_updateAssociations: (type, name, data) ->
Em.get(type, 'associationsByName').forEach (key, meta) =>
if meta.kind == 'belongsTo'
id = data["#{key}_id"]
if clientId = @typeMapFor(meta.type).idToCid[id]
if parent = this.findByClientId(meta.type, clientId, id)
dataProxy = parent.get('data')
if ids = dataProxy.get("#{name}_ids")
ids.pushObject(data.id) unless data.id in ids
parent.send('didChangeData');