ব্যাকবোন.জেজে নেস্টেড মডেলগুলি, কীভাবে যোগাযোগ করা যায়


117

আমি একটি সার্ভার থেকে নিম্নলিখিত JSON সরবরাহ পেয়েছি। এটির সাথে আমি নেস্টেড মডেল সহ একটি মডেল তৈরি করতে চাই। আমি নিশ্চিত না যে এটি অর্জনের উপায়।

//json
[{
    name : "example",
    layout : {
        x : 100,
        y : 100,
    }
}]

আমি এগুলি নিম্নলিখিত কাঠামো সহ দুটি নেস্টেড ব্যাকবোন মডেলগুলিতে রূপান্তরিত করতে চাই:

// structure
Image
    Layout
...

সুতরাং আমি লেআউট মডেলটিকে এর মতো সংজ্ঞায়িত করি:

var Layout = Backbone.Model.extend({});

তবে চিত্রের মডেলটি সংজ্ঞায়িত করার জন্য নীচের দুটি কৌশলগুলির মধ্যে (যদি কোনও হয়) আমার ব্যবহার করা উচিত? A বা B নীচে?

একজন

var Image = Backbone.Model.extend({
    initialize: function() {
        this.set({ 'layout' : new Layout(this.get('layout')) })
    }
});

বা,

var Image = Backbone.Model.extend({
    initialize: function() {
        this.layout = new Layout( this.get('layout') );
    }
});

উত্তর:


98

আমার ব্যাকবোন অ্যাপ্লিকেশনটি লেখার সময় আমার খুব একই সমস্যা রয়েছে। এম্বেড / নেস্টেড মডেলগুলির সাথে ডিল করতে হবে। আমি কিছু টুইটগুলি করেছি যা আমি ভেবেছিলাম বেশ মার্জিত সমাধান।

হ্যাঁ, আপনি বস্তুর চারপাশে কোনও বৈশিষ্ট্য পরিবর্তন করতে পার্স পদ্ধতিটি পরিবর্তন করতে পারেন, তবে সেগুলি আসলে বেশিরভাগ অবাস্তব কোড আইএমও এবং সমাধানের চেয়ে হ্যাকের বেশি মনে হয়।

আপনার উদাহরণের জন্য আমি যা পরামর্শ দিচ্ছি তা এখানে:

প্রথমে আপনার লেআউট মডেলটিকে সংজ্ঞায়িত করুন।

var layoutModel = Backbone.Model.extend({});

তারপরে আপনার চিত্রের মডেলটি এখানে:

var imageModel = Backbone.Model.extend({

    model: {
        layout: layoutModel,
    },

    parse: function(response){
        for(var key in this.model)
        {
            var embeddedClass = this.model[key];
            var embeddedData = response[key];
            response[key] = new embeddedClass(embeddedData, {parse:true});
        }
        return response;
    }
});

লক্ষ্য করুন যে আমি নিজেই মডেলটিতে কোনও ছলচাতুরী করি নি, কেবল পার্স পদ্ধতি থেকে কাঙ্ক্ষিত বস্তুটি ফিরিয়ে দিয়েছি।

আপনি যখন সার্ভার থেকে পড়ছেন তখন এটি নেস্টেড মডেলের কাঠামোটি নিশ্চিত করা উচিত। এখন, আপনি লক্ষ্য করবেন যে সংরক্ষণ বা সেটিংটি এখানে আসলে পরিচালনা করা হয় না কারণ আমি অনুভব করি যে সঠিকভাবে মডেলটি ব্যবহার করে নেস্টেড মডেলটি স্পষ্টভাবে সেট করা আপনার পক্ষে বোধগম্য।

তাই ভালো:

image.set({layout : new Layout({x: 100, y: 100})})

এছাড়াও নোট করুন যে আপনি প্রকৃতপক্ষে আপনার নেস্টেড মডেলটিতে পার্স পদ্ধতিটি কল করে কল করছেন:

new embeddedClass(embeddedData, {parse:true});

modelআপনার প্রয়োজন মতো ক্ষেত্রের নেস্টেড মডেলগুলি সংজ্ঞায়িত করতে পারেন ।

অবশ্যই, আপনি যদি নিজের টেবিলে নেস্টেড মডেলটি যতটা সংরক্ষণ করতে চান। এটি যথেষ্ট হবে না। সামগ্রিকভাবে পড়তে ও সংরক্ষণ করার ক্ষেত্রে এই সমাধানটি যথেষ্ট should


4
এটি দুর্দান্ত .. এটি অন্যান্য পদ্ধতির চেয়ে ক্লিয়ার হিসাবে গ্রহণযোগ্য উত্তর হওয়া উচিত। আমার কাছে কেবল পরামর্শগুলি হ'ল আপনার ক্লাসের প্রথম অক্ষরকে মূলধন করা যা পাঠযোগ্যতার জন্য ব্যাকবোন.মোডেলকে প্রসারিত করে .. যেমন চিত্রমোডেল এবং লেআউটমোডেল
স্টিফেন হ্যান্ডলি

1
@ স্টেফেনহ্যান্ডলি মন্তব্য এবং আপনার পরামর্শের জন্য ধন্যবাদ। তথ্যের জন্য, আমি এটি প্রয়োজনীয় জেএস এর প্রসঙ্গে ব্যবহার করছি। সুতরাং, মূলধনের বিষয়ে জবাব দেওয়ার জন্য, ভার 'চিত্রমোডেল' আসলে জেএসএসে ফিরে আসে। এবং মডেলটির রেফারেন্সটি নিম্নলিখিত নির্মাণ দ্বারা আবদ্ধ হবে: define(['modelFile'], function(MyModel){... do something with MyModel}) তবে আপনি ঠিক বলেছেন। আপনার প্রস্তাবিত কনভেনশন দ্বারা মডেলটি উল্লেখ করার অভ্যাসটি আমি করি।
রাইফুং

@ BobS দুঃখিত, একটি টাইপ ছিল। সাড়া দেওয়া উচিত ছিল। আমি এটি স্থির করেছি, নির্দেশ করার জন্য ধন্যবাদ।
রাইফুফং

2
নিস! আমি এই Backbone.Model.prototype.parseফাংশন এ যোগ করার পরামর্শ দিচ্ছি । তারপরে, আপনার সমস্ত মডেলগুলি হ'ল সাব মডেল অবজেক্টের ধরণগুলি (আপনার "মডেল" বৈশিষ্ট্যে) নির্ধারণ করতে হবে।
jasop

1
শান্ত! আমি অনুরূপ কিছু করার জন্য ক্ষতবিক্ষত করেছি (উল্লেখযোগ্যভাবে এবং দুঃখের সাথে আমি এই উত্তরটি খুঁজে পাওয়ার পরে) এবং এটি এখানে লিখেছি: blog.untrod.com/2013/08/declarative-approach-to-nesting.html বড় পার্থক্য হ'ল গভীরভাবে নেস্টেড মডেলগুলির জন্য আমি রুট / প্যারেন্ট মডেলটিতে একবারে পুরো ম্যাপিং ঘোষণা করি এবং কোডটি সেখান থেকে নিয়ে যায় এবং ব্যাকবোন সংগ্রহ এবং মডেলগুলিতে প্রাসঙ্গিক বস্তুগুলিকে হাইড্রেট করে পুরো মডেলটি অনুসরণ করে চলে যায়। কিন্তু সত্যিই একটি খুব অনুরূপ পদ্ধতির।
ক্রিস ক্লার্ক

16

আমি এই কোডটি পার্সকে নতুন করে সংজ্ঞায়িত করার জন্য পিটার লিয়নের পরামর্শের উদাহরণ হিসাবে পোস্ট করছি। আমার একই প্রশ্ন ছিল এবং এটি আমার জন্য কাজ করেছে (একটি রেল ব্যাকএন্ড সহ)। এই কোডটি কফিস্ক্রিপ্টে লেখা হয়েছে। এর সাথে অপরিচিত লোকদের জন্য আমি কয়েকটি বিষয় স্পষ্ট করে দিয়েছি।

class AppName.Collections.PostsCollection extends Backbone.Collection
  model: AppName.Models.Post

  url: '/posts'

  ...

  # parse: redefined to allow for nested models
  parse: (response) ->  # function definition
     # convert each comment attribute into a CommentsCollection
    if _.isArray response
      _.each response, (obj) ->
        obj.comments = new AppName.Collections.CommentsCollection obj.comments
    else
      response.comments = new AppName.Collections.CommentsCollection response.comments

    return response

বা, জেএসে in

parse: function(response) {
  if (_.isArray(response)) {
    return _.each(response, function(obj) {
      return obj.comments = new AppName.Collections.CommentsCollection(obj.comments);
    });
  } else {
    response.comments = new AppName.Collections.CommentsCollection(response.comments);
  }
  return response;
};

উদাহরণ কোডের জন্য প্রপস এবং ওভাররাইড পার্সের পরামর্শ দেওয়া হচ্ছে। ধন্যবাদ!
এডওয়ার্ড অ্যান্ডারসন

11
আপনার উত্তরটি আসল জেএসে পেয়ে ভালো লাগবে
জেসন

6
কফিসিপি সংস্করণ পেয়ে খুশি, ধন্যবাদ অন্যদের জন্য, js2coffee.org
ABCD.ca

16
যদি প্রশ্নটি আসল জেএস হয় তবে একটি উত্তরও হওয়া উচিত।
ম্যানুয়েল হার্নান্দেজ

12

ব্যাকবোন-অ্যাসোসিয়েশনগুলিBackbone.AssociatedModel থেকে ব্যবহার করুন :

    var Layout = Backbone.AssociatedModel.extend({
        defaults : {
            x : 0,
            y : 0
        }
    });
    var Image = Backbone.AssociatedModel.extend({
        relations : [
            type: Backbone.One,
            key : 'layout',
            relatedModel : Layout          
        ],
        defaults : {
            name : '',
            layout : null
        }
    });

সুন্দর সমাধান। : সেখানে আউট একটি অনুরূপ প্রকল্প খুব নেই github.com/PaulUithol/Backbone-relational
michaelok

11

আমি নিশ্চিত না যে ব্যাকবোন নিজেই এটি করার একটি প্রস্তাবিত উপায় আছে। লেআউট অবজেক্টটির কি ব্যাক এন্ড ডাটাবেসে নিজস্ব আইডি এবং রেকর্ড রয়েছে? যদি তাই হয় তবে এটি নিজের মতো করে নিজের মডেল তৈরি করতে পারেন। যদি তা না হয় তবে আপনি এটিকে নেস্টেড ডকুমেন্ট হিসাবে রেখে যেতে পারেন, এটি নিশ্চিত করে নিন যে আপনি এটিকে JSON থেকে saveএবং parseপদ্ধতিতে সঠিকভাবে রূপান্তর করেছেন । আপনি শেষ পর্যন্ত ভালো একটি পন্থা গ্রহণ করেন তাহলে, আমি মনে করি আপনার একটি উদাহরণ মেরুদন্ড সঙ্গে আরো সামঞ্জস্যপূর্ণ যেহেতু হয় setসঠিকভাবে আপডেট হবে attributes, কিন্তু আবার আমি নিশ্চিত কি দাঁড়া ডিফল্টরূপে নেস্টেড মডেলের সঙ্গে কাজ করে না। সম্ভবত এটি হ্যান্ডেল করার জন্য আপনার কিছু কাস্টম কোড প্রয়োজন।


আহ! দুঃখিত, এটি newঅপারেটরটি হারিয়েছে । এই ভুলটি সংশোধন করার জন্য আমি এটি সম্পাদনা করেছি।
রস

ওহ, তাহলে আমি আপনার প্রশ্নের ভুল ব্যাখ্যা করেছিলাম। আমি আমার উত্তর আপডেট করব।
পিটার লিয়নস

8

আপনি যদি বিষয়গুলি সহজ রাখতে চান তবে আমি অপশন বি দিয়ে যাব।

আর একটি ভাল বিকল্প ব্যাকবোন-রিলেশনাল ব্যবহার করা হবে । আপনি ঠিক এর মতো কিছু সংজ্ঞায়িত করতে চাই:

var Image = Backbone.Model.extend({
    relations: [
        {
            type: Backbone.HasOne,
            key: 'layout',
            relatedModel: 'Layout'
        }
    ]
});

+1 ব্যাকবোন-রিলেশনাল বেশ প্রতিষ্ঠিত বলে মনে হচ্ছে: নিজস্ব ওয়েবসাইট, 1.6k তারা, 200+ কাঁটাচামচ।
রস

6

নেস্টেড মডেল এবং বৈশিষ্ট্যগুলির জন্য আমি ব্যাকবোন ডিপমোডেল প্লাগইন ব্যবহার করি।

https://github.com/powmedia/backbone-deep-model

আপনি ইভেন্টগুলির এন স্তরগুলিকে আরও গভীর করতে বাঁধতে পারেন। উদাহরণ স্বরূপ: model.on('change:example.nestedmodel.attribute', this.myFunction);


5

রাইফুংয়ের সুন্দর উত্তরের কফিস্ক্রিপ্ট সংস্করণ :

class ImageModel extends Backbone.Model
  model: {
      layout: LayoutModel
  }

  parse: (response) =>
    for propName,propModel of @model
      response[propName] = new propModel( response[propName], {parse:true, parentModel:this} )

    return response

মিষ্টি না? ;)


11
আমি আমার জাভাস্ক্রিপ্টে চিনি নেব না:)
রস

2

আমার একই সমস্যা ছিল এবং আমি রাইফুংয়ের উত্তরে কোডটি নিয়ে পরীক্ষা-নিরীক্ষা করছি , এটি একটি দুর্দান্ত পরামর্শ।
তবে, আপনি না করতে চান setনেস্টেড মডেলের সরাসরি, বা ক্রমাগত পাস করতে চান না {parse: true}optionsআরেকটি পদ্ধতির পুনরায় সংজ্ঞায়িত করতে হবে setনিজেই।

ইন দাঁড়া 1.0.0 , setবলা হয় constructor, unset, clear, fetchএবংsave

নীড় সুপার মডেলটি বিবেচনা করুন , নীড় মডেল এবং / অথবা সংগ্রহের প্রয়োজন এমন সমস্ত মডেলের জন্য।

/** Compound supermodel */
var CompoundModel = Backbone.Model.extend({
    /** Override with: key = attribute, value = Model / Collection */
    model: {},

    /** Override default setter, to create nested models. */
    set: function(key, val, options) {
        var attrs, prev;
        if (key == null) { return this; }

        // Handle both `"key", value` and `{key: value}` -style arguments.
        if (typeof key === 'object') {
            attrs = key;
            options = val;
        } else {
            (attrs = {})[key] = val;
        }

        // Run validation.
        if (options) { options.validate = true; }
        else { options = { validate: true }; }

        // For each `set` attribute, apply the respective nested model.
        if (!options.unset) {
            for (key in attrs) {
                if (key in this.model) {
                    if (!(attrs[key] instanceof this.model[key])) {
                        attrs[key] = new this.model[key](attrs[key]);
                    }
                }
            }
        }

        Backbone.Model.prototype.set.call(this, attrs, options);

        if (!(attrs = this.changedAttributes())) { return this; }

        // Bind new nested models and unbind previous nested models.
        for (key in attrs) {
            if (key in this.model) {
                if (prev = this.previous(key)) {
                    this._unsetModel(key, prev);
                }
                if (!options.unset) {
                    this._setModel(key, attrs[key]);
                }
            }
        }
        return this;
    },

    /** Callback for `set` nested models.
     *  Receives:
     *      (String) key: the key on which the model is `set`.
     *      (Object) model: the `set` nested model.
     */
    _setModel: function (key, model) {},

    /** Callback for `unset` nested models.
     *  Receives:
     *      (String) key: the key on which the model is `unset`.
     *      (Object) model: the `unset` nested model.
     */
    _unsetModel: function (key, model) {}
});

লক্ষ্য করুন যে model, _setModelএবং _unsetModelউদ্দেশ্য ফাঁকা রাখা হয়। বিমূর্তির এই স্তরে আপনি সম্ভবত কলব্যাকগুলির জন্য কোনও যুক্তিসঙ্গত ক্রিয়া সংজ্ঞায়িত করতে পারবেন না। তবে আপনি তাদের সাবমোডেলগুলিতে প্রসারিত করতে ওভাররাইড করতে চাইতে পারেন CompoundModel
এই কলব্যাকগুলি শ্রোতাদের বাঁধা এবং changeইভেন্টগুলি প্রচার করতে উদাহরণস্বরূপ কার্যকর are


উদাহরণ:

var Layout = Backbone.Model.extend({});

var Image = CompoundModel.extend({
    defaults: function () {
        return {
            name: "example",
            layout: { x: 0, y: 0 }
        };
    },

    /** We need to override this, to define the nested model. */
    model: { layout: Layout },

    initialize: function () {
        _.bindAll(this, "_propagateChange");
    },

    /** Callback to propagate "change" events. */
    _propagateChange: function () {
        this.trigger("change:layout", this, this.get("layout"), null);
        this.trigger("change", this, null);
    },

    /** We override this callback to bind the listener.
     *  This is called when a Layout is set.
     */
    _setModel: function (key, model) {
        if (key !== "layout") { return false; }
        this.listenTo(model, "change", this._propagateChange);
    },

    /** We override this callback to unbind the listener.
     *  This is called when a Layout is unset, or overwritten.
     */
    _unsetModel: function (key, model) {
        if (key !== "layout") { return false; }
        this.stopListening();
    }
});

এটির সাহায্যে আপনার স্বয়ংক্রিয় নেস্টেড মডেল তৈরি এবং ইভেন্টের প্রচার রয়েছে। নমুনা ব্যবহারও সরবরাহ করা হয় এবং পরীক্ষিত হয়:

function logStringified (obj) {
    console.log(JSON.stringify(obj));
}

// Create an image with the default attributes.
// Note that a Layout model is created too,
// since we have a default value for "layout".
var img = new Image();
logStringified(img);

// Log the image everytime a "change" is fired.
img.on("change", logStringified);

// Creates the nested model with the given attributes.
img.set("layout", { x: 100, y: 100 });

// Writing on the layout propagates "change" to the image.
// This makes the image also fire a "change", because of `_propagateChange`.
img.get("layout").set("x", 50);

// You may also set model instances yourself.
img.set("layout", new Layout({ x: 100, y: 100 }));

আউটপুট:

{"name":"example","layout":{"x":0,"y":0}}
{"name":"example","layout":{"x":100,"y":100}}
{"name":"example","layout":{"x":50,"y":100}}
{"name":"example","layout":{"x":100,"y":100}}

2

আমি বুঝতে পারি যে আমি এই পার্টিতে দেরি করেছি, তবে আমরা এই দৃশ্যের সাথে সামঞ্জস্য করার জন্য একটি প্লাগইন সম্প্রতি প্রকাশ করেছি। একে ব্যাকবোন-নেস্টিফাই বলা হয় ।

সুতরাং আপনার নেস্টেড মডেলটি অপরিবর্তিত রয়েছে:

var Layout = Backbone.Model.extend({...});

তারপরে সমন্বিত মডেলটি সংজ্ঞায়িত করার সময় প্লাগইনটি ব্যবহার করুন ( অ্যান্ডস্কোর.একসেটড ব্যবহার করে ):

var spec = {
    layout: Layout
};
var Image = Backbone.Model.extend(_.extend({
    // ...
}, nestify(spec));

এর পরে, ধরে নিলে আপনার কাছে এমন একটি মডেল রয়েছে mযা একটি উদাহরণ Image, এবং আপনি প্রশ্নটি থেকে JSON সেট করেছেন m, আপনি এটি করতে পারেন:

m.get("layout");    //returns the nested instance of Layout
m.get("layout|x");  //returns 100
m.set("layout|x", 50);
m.get("layout|x");  //returns 50

2

ব্যাকবোন-ফর্মগুলি ব্যবহার করুন

এটি নেস্টেড ফর্মগুলি, মডেলগুলি এবং জেএসওএন সমর্থন করে। সমস্ত প্রয়োজন

var Address = Backbone.Model.extend({
    schema: {
    street:  'Text'
    },

    defaults: {
    street: "Arteaga"
    }

});


var User = Backbone.Model.extend({
    schema: {
    title:      { type: 'Select', options: ['Mr', 'Mrs', 'Ms'] },
    name:       'Text',
    email:      { validators: ['required', 'email'] },
    birthday:   'Date',
    password:   'Password',
    address:    { type: 'NestedModel', model: Address },
    notes:      { type: 'List', itemType: 'Text' }
    },

    constructor: function(){
    Backbone.Model.apply(this, arguments);
    },

    defaults: {
    email: "x@x.com"
    }
});

var user = new User();

user.set({address: {street: "my other street"}});

console.log(user.toJSON()["address"]["street"])
//=> my other street

var form = new Backbone.Form({
    model: user
}).render();

$('body').append(form.el);

1

আপনি এখনও অন্য ফ্রেমওয়ার্ক যুক্ত করতে না চান, আপনি উপেক্ষিত সঙ্গে একটি বেস বর্গ তৈরি বিবেচনা করতে পারেন setএবং toJSONএবং এর মতো এটিকে ব্যবহার করুন:

// Declaration

window.app.viewer.Model.GallerySection = window.app.Model.BaseModel.extend({
  nestedTypes: {
    background: window.app.viewer.Model.Image,
    images: window.app.viewer.Collection.MediaCollection
  }
});

// Usage

var gallery = new window.app.viewer.Model.GallerySection({
    background: { url: 'http://example.com/example.jpg' },
    images: [
        { url: 'http://example.com/1.jpg' },
        { url: 'http://example.com/2.jpg' },
        { url: 'http://example.com/3.jpg' }
    ],
    title: 'Wow'
}); // (fetch will work equally well)

console.log(gallery.get('background')); // window.app.viewer.Model.Image
console.log(gallery.get('images')); // window.app.viewer.Collection.MediaCollection
console.log(gallery.get('title')); // plain string

আপনার BaseModelএই উত্তরটি দরকার (উপলভ্য, যদি আপনি অভিনব হন তবে একটি টুকরো হিসাবে ) as


1

আমাদেরও এই সমস্যা রয়েছে এবং একটি টিম কর্মী ব্যাকবোন-নেস্টেড-বৈশিষ্ট্যযুক্ত প্লাগইন প্রয়োগ করেছেন।

ব্যবহার খুব সহজ। উদাহরণ:

var Tree = Backbone.Model.extend({
  relations: [
    {
      key: 'fruits',
      relatedModel: function () { return Fruit }
    }
  ]
})

var Fruit = Backbone.Model.extend({
})

এটির সাহায্যে ট্রি মডেল তারপরে ফলগুলি অ্যাক্সেস করতে পারে:

tree.get('fruits')

আপনি এখানে আরও তথ্য দেখতে পারেন:

https://github.com/dtmtec/backbone-nested-attributes

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.