Backbone.Model Gotcha With options.url

Há uma (talvez) pegadinha peculiar a ser observada com o Backbone.Model e certos atributos passados ​​como opções versus atributos.

tl; dr Passar um parâmetro de url para uma collection.fetch()chamada definirá esse url no Backbone.Model diretamente


ATUALIZAÇÃO: O “bug” específico descrito nesta postagem foi removido no branch master atual do projeto, mas não fazia parte do lançamento oficial no momento em que este artigo foi escrito.


Aqui está um exemplo que já me mordeu duas vezes. Depois disso, terminaremos com uma solução melhor.

Em um, Marionette.CollectionVieweu estava tentando fazer um carregamento paginado da Backbone.Collectioninstância do modo de exibição . O código a seguir foi modificado para fins de exemplo:

if @gallery.get('page') < @gallery.get("total_pages")
nextPageUrl
= "#{@gallery.url()}?page=#{@gallery.get("next_page")&per=#{@gallery.get("per_page")}"
@collection.fetch(url: nextPageUrl,remove: false).done( => ...)

As opções passadas para a maioria dos métodos do Backbone serão passadas totalmente para quaisquer métodos xhr e callback subsequentes intactos (geralmente por meio de a _.clone). Se options.urlfor fornecido, o mesmo urlestará no optionshash que é passado para a instanciação da nova chamada de Backbone.Model como parte do comando resetou setno fetch()retorno de chamada de sucesso.

Normalmente, isso não causa efeitos colaterais indesejados, pois é o primeiro attrsparâmetro de hash definido no modelo, e não o optionshash. No entanto, o Backbone.Model tem três muito especiais modelOptionsque serão anexados diretamente ao modelo, se fornecidos :

var modelOptions = ['url', 'urlRoot', 'collection'];

E dentro da declaração da função Backbone.Model, eles modelOptionssão usados ​​por meio de:

_.extend(this, _.pick(options, modelOptions));

Portanto, usando o código de exemplo, cada modelo retornado da busca com tem seu urlatributo definido para qualquer valor calculado de nextPageUrlestava na chamada de busca. Não importa o que urlRootou urlfunções / atributos você declarou nesses modelos, a url é agora o que estava em .options.url

Voltando à minha implementação incorreta original, a maneira correta de fazer isso é criar um urlmétodo na própria coleção que cria a url dinâmica e, em seguida, você pode simplesmente chamar @collection.fetch(remove: false)sem a necessidade de um parâmetro de url.