Saving Entries to Database Relationship (many-to-m

2019-06-03 04:27发布

问题:

I currently have two Backbone models: user and project. I would like to have a Backbone view containing a form that enables the creation of a new project, and the association of currently existing users (entries from the database users table) with this project. When a user completes this form and clicks the save button, the new project should be saved into the database (in the projects table) and the relationship between the saved project and the related users should be saved into a relationship table (projects_users table, containing the corresponding project id and the user id for each relationship). Currently, I can save the project information, but could not get any data into the projects_users table using Backbone-relational.

What do you think the best approach to achieve the above functionality is? It would be great if you could point me to specific code that I could use as a template.

Thank you, Alexandra

回答1:

After some frustrating trial-and-error period, I finally managed to get my code working! It's not beautiful, but it is functional, and now I can start thinking about improving it. Hopefully, some other people will find this information useful ...

The one thing that put me on the right track was the understanding that what needed to be changed was not only in the backbone view code (the one with the new projects form), but also in the corresponding rails models.

For the rails part (Rails 3.2.2), I made sure that the following model files had the necessary information:

project.rb

class Project < ActiveRecord::Base
  has_and_belongs_to_many :users

  #attr_accessible :name, :description, :users_attributes
  #has_many :projects_users, foreign_key: "project_id", dependent: :destroy
  #has_many :users, through :projects_users
  #accepts_nested_attributes_for :users
end

user.rb

class User < ActiveRecord::Base
  has_and_belongs_to_many :projects
end

projects_users.rb

class ProjectsUsers < ActiveRecord::Base
    belongs_to :project
    belongs_to :user
end

I have read in many different places that has_and_belongs_to_many is not the best way to set many-to-many relationships in rails. Nevertheless, I could not get the same functionality using the has_many definition - the commented part in project.rb is the way I tried this different approach. The file user.rb had some corresponding code, which I removed for simplicity.

Now, what I needed to get done in the backbone form view was to send a POST request with a JSON object that the rails projects_controller.rb could recognize. Initially, I tried several POST requests without success (and no errors to guide me). But then, I remembered to have previously implemented a form for teams where users could be added to a particular team (HABTM Checkboxes - there is a railscast for this functionality). After looking at this example, I realized what was needed from my POST request. This is what I wanted to see in the rails server log file:

Started POST "/projects" for 127.0.0.1 at 2012-06-27 00:35:22 +0000
Processing by ProjectsController#create as JSON
  Parameters: {"project"=>{"description"=>"with some description", "user_ids"=>["101", "1", "99"], "name"=>"some new project"}}

Backbone relevant files to achieve the above request:

project.js

App.Models.Project = Backbone.Model.extend({
  urlRoot: '/projects',

  // Default attributes for the project.
  defaults: {
    description: "",
    user_ids: []
  },

  /* getters */      
});

user.js

App.Models.User = Backbone.Model.extend({
  /* getters */
});

form.js

App.Views.Projects.Common.Form = Backbone.View.extend({
  ...
  events: {
    "submit #new_project_form"   : "formSubmit"
  },

  formSubmit: function(event) {
    this.submitted($(event.target));
    return false;
  },

  submitted: function(formElement) {
    var newData = this.serializeFormData(formElement);
    this.model = new App.Models.Project({
      name        : newData.name,
      description : newData.description
    });

    this.saveFormData(newData);
    return false;
  },

  serializeFormData: function(formElement) {
    var fields = formElement.serializeArray();

    var serializedData = {};
    $.each(fields, function(index, field) {
      serializedData[field.name] = field.value;
    });

    return serializedData;
  },

  // THE IMPORTANT PART FOR THE POST REQUEST
  saveFormData: function(newData) {

    // preserve reference to view for callbacks
    var self = this;
    var project = this.model;

    project.set({
      // a list of user ids associated with a project
      "user_ids" :  this.view_variables.user_ids
    });

    var project_object = ({
      "project" :   _.clone(project.attributes)
    });

    $.ajax({
      type: 'POST',
      url: '/projects',
      data: project_object,
      dataType: "json",
      success: function() {
        self.$el.hide();
        self.addNewModelToCollection();
      }
    });

  },
  ...
});

The code is kind of verbose, and includes some code that is specific to my project. Still, the relevant part is in the saveFormData function, where the jQuery ajax function is used.

In case you have any suggestions, either for the rails or for the Backbone part, please let me know. I will be happy to learn how to improve this solution.



回答2:

I know it's old post but this looks interesting: http://backbonerelational.org/