I am trying to build a ruby on rails and graphQL app, and am working on a user update mutation. I have spent a long time trying to figure it out, and when I accidentally made a typo, it suddenly worked.
The below is the working migration:
module Mutations
class UpdateUser < BaseMutation
argument :id, Int
argument :first_name, String
argument :last_name, String
argument :username, String
argument :email, String
argument :password, String
field :user, Types::User
field :errors, [String], null: false
def resolve(id:, first_name:, last_name:, username:, email:, password:)
user = User.find(id)
user.update(first_name:, last_name:, username:, email:, password:)
{ user:, errors: [] }
rescue StandardError => e
{ user: nil, errors: [e.message] }
end
end
end
The thing I am confused about is when I define the arguments, they are colon first: eg :id
or :first_name
When I pass them to the resolve method they only work if they have the colon after: eg id:
or first_name:
When I pass the variables to the update method, they use the same syntax of colon after, for all variables other than ID. For some reason, when I used id:
it was resolving to a string "id", and using colon first :id
was returning an undefined error.
It is only when I accidentally deleted the colon, and tried id
that it actually resolved to the passed through value.
My question for this, is why and how this is behaving this way? I have tried finding the answer in the docs, and reading other posts, but have been unable to find an answer.
Please someone help my brain get around this, coming from a PHP background, ruby is melting my brain.
CodePudding user response:
It's going to take some time to get used to Ruby, coming from PHP, but it won't be too bad.
Essentially id
is a variable, or object/model attribute when used like model_instance.id
. In PHP this would be like $id
or $object_instance->id
.
When you see id:
it is the key in a key-value pair, so it expects something (a value) after it (or assumes nil
if nothing follows, often in method definitions using keyword arguments like your example). A typical use might be model_instance.update(id: 25)
where you are essentially passing in a hash to the update
method with id
as the key and 25
as the value. The older way to write this in Ruby is with a "hash rocket" like so: model_instance.update(:id => 25)
.
More reading on Ruby hashes: https://www.rubyguides.com/2020/05/ruby-hash-methods
More reading on keyword arguments: https://www.rubyguides.com/2018/06/rubys-method-arguments
Now if you're paying attention that hash rocket now uses the 3rd type you're asking about. When you see a colon preceding a string like that it is called a "symbol" and it will take some time to get used to them but they are essentially strings in Ruby that are one character fewer to define. (I mean there is more to it than that, but you will learn that as you go.) Instead of using 'id'
or "id"
as a string, Ruby folks like to use :id
as a symbol and it will typically auto-convert to a string when needed. A good example might be an enumerator of sorts.
state = :ready
if sate == :ready
state = :finished
else
state = :undefined
end
More reading on Ruby symbols: https://www.rubyguides.com/2018/02/ruby-symbols