0

I am using Graphql mutation to save a User that looks kinda like this:

class CreateUser < Mutations::BaseMutation
    argument :email, String, required: true
    argument :password, String, required: true
    argument :password_confirmation, String, required: true
    argument :first_name, String, required: false
    argument :last_name, String, required: false
    argument :middle_name, String, required: false
    argument :source, String, required: false

    field :user, Types::UserType, null: true
    field :token, String, null: true

    def resolve(args)
          user = User.new(password: args[:password], password_confirmation: args[:password_confirmation], email: args[:email])
    
          profile = user.build_profile
          profile.first_name = args[:first_name] if args[:first_name].present?
          profile.last_name = args[:last_name] if args[:last_name].present?
          profile.middle_name = args[:middle_name] if args[:middle_name].present?
          user.save!
    
          UserMailer.with(user: user).send_initial_password_instructions.deliver_now if args[:source].present?
    
          # current_user needs to be set so authenticationToken can be returned
          context[:current_user] = user
    
          MutationResult.call(obj: { user: user, token: user.authentication_token }, success: user.persisted?, errors: user.errors.full_messages)
     end
end

All good here. BUT... I have a model named Contact. Which is quite empty:

class Contact < ApplicationRecord
  belongs to :user, optional: true
end

So what I am trying to do is to have a method created on Contact that whenever I create a User I can send some args to Contact and let the Contact method execute the save!

This is what I've been trying: Contact.rb

def self.create_with_user(args)
    contact = Contact.new(args)
    contact.user = User.new(email: args[:email], password: args[:password], password_confirmation: args[:password_confirmation])
    contact.user.save!
  end

This is what I've been trying: create_user.rb (graphql mutation)

def resolve(args)
          user = User.new(password: args[:password], password_confirmation: args[:password_confirmation], email: args[:email])

          profile = user.build_profile
          profile.first_name = args[:first_name] if args[:first_name].present?
          profile.last_name = args[:last_name] if args[:last_name].present?
          profile.middle_name = args[:middle_name] if args[:middle_name].present?

          contact = Contact.create_with_user(args)
          user.contact = contact

          user.save!

          UserMailer.with(user: user).send_initial_password_instructions.deliver_now if args[:source].present?
          

          # current_user needs to be set so authenticationToken can be returned
          context[:current_user] = user

          MutationResult.call(obj: { user: user, token: user.authentication_token }, success: user.persisted?, errors: user.errors.full_messages)
     end

But this results into a NoMethodError Exception: undefined method 'to' for Contact:Class. Newbie rails here so I am really interested in learning this. Thankyou

1 Answer 1

1

The error was generated from contact.rb you have a type its belongs_to but you have belongs to.

contact.rb

class Contact < ApplicationRecord
  belongs to :user, optional: true
end

Preferred Solutions

If the creation of the Contact should always happen and you don't have any custom params from the endpoint, use a callback on the User model.

user.rb

class User < ApplicationRecord
  after_create :create_contact

  private

  def create_contact
    Contact.create(user: self, .....) # the other params you need to pass from model
  end
end

If you have custom params from the endpoint you can use accepts_nested_attributes_for and make the contact params nested on the user.

params = {
  user: {
    user_params,
    contact: {
      contact_params
    }
  }
}

user.rb

class User < ApplicationRecord
  accepts_nested_attributes_for :contact
end
Sign up to request clarification or add additional context in comments.

11 Comments

Hello!! Thanks for the response friend!!! I don't have nested parameters, which makes it easier for me. But, with the callback, there is no need to call a method from a model to the Mutation? Callbacks looks more easier.
Whenever I get to the callback method. I get this issue: def create_contact byebug Contact.create!(user: self, first_name: first_name, last_name: last_name, email: email) end *** NoMethodError Exception: undefined method 'to' for Contact:Class Does this mean my user-contact relationship us quite wrong?
@theKid It seems that you have an error on the Contact.rb file.
This is the only thing I have on my Contact.rb file: class Contact < ApplicationRecord belongs to :user, optional: true end
@theKid You have the wrong syntax on your cotanct.rb file. It's belongs_to not belongs to.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.