How to save hasMany association in one Ember.js form using Ember Data & Rails?

I'm having trouble figuring out the right way to keep hasMany associations with a single form using Ember.js, Ember Data, and Rails. The client has many projects. I have a new project form that has two fields: project name and client name. http://cl.ly/image/3z0P0R3M1t2u

I tried to save my creation logic in Ember.js ClientsController and ProjectsController, but will I need to transfer some of this to the submit action on my ProjectNewView?

Update: I updated my code after detecting this problem. I'm getting closer, but the Rails ProjectsController is still not getting the associated client_id. It is not part of the parameters that the controller receives. It still seems that I probably wonโ€™t do it in the best way.

Model:

Rails

class Client < ActiveRecord::Base attr_accessible :name has_many :projects accepts_nested_attributes_for :projects validates :name, :presence => true end class Project < ActiveRecord::Base attr_accessible :name, :client_id belongs_to :client validates :name, :presence => true validates :client, :presence => true end 

ember.js

 App.Client = DS.Model.extend name: DS.attr('string') projects: DS.hasMany('App.Project', { embedded: true }) validate: -> if @get('name') is null or @get('name') is '' 'Client requires a name.' App.Project = DS.Model.extend name: DS.attr('string') client: DS.belongsTo('App.Client') validate: -> if @get('name') is `undefined` or @get('name') is null or @get('name') is '' return 'Projects require a name.' if @get('client') is `undefined` or @get('client') is null or @get('client') is '' 'Projects require a client.' 

Controllers

Rails

 class Api::ClientsController < Api::BaseController def create @client = Client.find_or_create_by_name(params[:client][:name]) respond_to do |format| if @client.save format.json { render json: @client, status: :create } else format.json { render json: @client.errors, status: :unprocessable_entry } end end end end class Api::ProjectsController < Api::BaseController def create @project = Project.new(params[:project]) respond_to do |format| if @project.save format.json { render json: @project, status: :created, location: @project } else format.json { render json: @project.errors, status: :unprocessable_entry } end end end end 

ember.js

 App.ClientsController = Em.ArrayController.extend createClient: (data) -> @transaction = App.store.transaction() client = @transaction.createRecord(App.Client, data) project_data = data.projects_attributes[0] client.get('projects').createRecord(project_data) validation_errors = client.validate() if validation_errors App.displayError validation_errors client.destroy() else @transaction.commit() App.ProjectsController = Em.ArrayController.extend createProject: (data) -> @transaction = App.store.transaction() project = @transaction.createRecord(App.Project, data) validation_errors = project.validate() if validation_errors App.displayError validation_errors project.destroy() else @transaction.commit() App.get('router').transitionTo('projects') 

Views:

ember.js

 App.ProjectsNewView = Em.View.extend classNames: ['form row'] tagName: 'form' templateName: 'projects/new' init: -> @_super() submit: (event) -> event.preventDefault() client = {} client.name = @get('client') project = {} project.name = @get('name') client.projects_attributes = [] client.projects_attributes.push project App.router.clientsController.createClient(client) 
+4
source share
1 answer

@David I'm not an expert, but I looked at your question again, and I think in order to get the client_id associated with it, you have to call the JSON method in RestAdapter and pass it:

 {associations: true} 

Below are links explaining how to do this:

https://stackoverflow.com/questions/10184213/is-there-a-way-to-post-embedded-objects-back-to-the-api-with-ember-data

Embedded Ember data objects stored as separate objects

Emberjs - unable to request inline model or association

Update

Before answering the question of where to use JSON in the code, I want to take one step back to something that I just watched with the design of your code.

You are trying to create a parent record in a child record because Client is a parent and project is a child. If you are observing well, issue-115 you contacted categorically states that parentRecord storage will be used to create the entry. Also, if you test the test in a balanced pull-request that has been merged in relation to issue-115 , you will see it again as Create a child entry in parentRecord .

But you do the opposite, that is, create parentRecord in the child entry . You need to undo this.

In addition, on the rails side , in the Client model, you call accepts_nested_attributes_for: projects , which, like emberjs, allows you to create recording projects from the client, and not vice versa. All examples of using accepts_nested_attributes_for in the rails , railscasts manual , and this is on the nested attributes , show the fields for the child model created from forms in the parent model.

Thus, both rails and emberjs are used in this case to create parentRecord from the child record. This may be the reason that you have a problem with the client ID. So cancel the design and try again. If it still does not send the client ID. Then you must call toJSON on the client model, which is the parent association, as shown in the first link , from the initial links that I wrote, recommending you name {association: true} on toJson in the restAdapter.

  App.Client ## toJSON: (options={}) -> options['associations'] = true @_super(options) 

Hope this helps. Please comment on what worked or didnโ€™t work, so that others experience similar problems who find this post can know where to start.

Finally, this does not prevent you from creating rails api with the active_model_serializer gem , which is ember - the main team recommended gem to create rails api for the ember and RestAdapter data. Thus, you can move and insert associations from both the ember side and the rail side.

+1
source

Source: https://habr.com/ru/post/1434380/


All Articles