Home > front end >  Calling model method and passing params Rails 6
Calling model method and passing params Rails 6

Time:07-13

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

CodePudding user response:

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
  • Related