简体   繁体   中英

rails syntax error: wrong number of arguments

while building a website with rails, I found a little syntax error that I really don't understand what caused it.

 class User < ApplicationRecord
   has_secure_password
   has_many :posts, dependent: :nullify
   has_many :comments, dependent: :nullify

   validates :first_name, :last_name, presence: true, length: {maximum: 30}
   validates :email, presence: true, uniqueness: true, format: /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i


   def full_name
     (first_name +" "+ last_name).titleize
   end

 end

this is model file for user. If I run this file, it causes an error: wrong number of arguments(given 1, expected 0). However if I give a space like so,

  def full_name
     (first_name + " "+ last_name).titleize
   end

It runs normally.

Although I know I can just ignore it, I'm just so curious about how the space causes argument error, it ain't no argument I think..

I also ran the same code in normal ruby by making my own titleize method in string class, it works fine without the space. so curious !

You can use ruby_parser to eliminate your doubts about how this is actually parsed.

RubyParser.for_current_ruby.parse '(first_name +" "+ last_name)' results in:

s(:call, nil,
         :first_name,
         s(:call, s(:call, s(:str, " "),
                           :+@),
                  :+,
                  s(:call, nil,
                           :last_name)))

Effectively, you're getting first_name((+" ") + last_name) , or in a more redundant/methody fashion, self.first_name((" ".+@).+(self.last_name)) .

Meaning there is an argument in a call of the first_name method, stemming from accidental use of +@ , the unary plus, on " " . But since first_name is an attribute getter (I guess?) and does not accept any arguments, you're getting an ArgumentError .


To help you interpret this output, a :call S-expression consists of:

  • :call
  • subject (a value on which a method is being called, nil if self )
  • method name as a symbol
  • 0 or more arguments

And by the way, Rubocop could have warned you about this:

Lint/AmbiguousOperator: Ambiguous positive number operator. Parenthesize the method
arguments if it's surely a positive number operator, or add a whitespace to the
right of the + if it should be a addition.
(first_name +" "+ last_name)
            ^

Consider adding it into your workflow.

This is likely going between the unary-plus operator and the binary-plus operator when you put code directly next to it.

unary plus is just like unary-minus eg -2 and I'm sure you understand the difference between writing 1 -2 and 1 - 2 ?

As an aside, the standard "ruby way" would be to interpolate rather than use concatenation, so your line would be better written:

"#{first_name} #{last_name}".titleize

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM