简体   繁体   中英

How does the post method work in Ruby on Rails

I come from a Python and Java background with only basic knowledge to CSS, HTML, Ruby and trying to learn web development using Ruby on Rails. I'm trying to follow the tutorial on Michael Hartl . I do not understand what arguments the post method in Listing 7.23 is doing.

require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
  end
end

From what I trace in the API , it takes in 2 non-optional arguments which are both Strings, but in Listing 7.23 there is a sudden hash syntax params: in the 2nd argument and this has confused me. Can anyone enlighten me?

I think you're looking at the wrong place, the link shows http.post . You want the IntegrationTest post .

From: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb

def post(path, **args)
  process(:post, path, **args)
end

And:

def process(method, path, params: nil, headers: nil, env: nil, xhr: false, as: nil)
  request_encoder = RequestEncoder.encoder(as)
  headers ||= {}

  # rest
end

Edit: The double splat

Ruby 2.0 added the keyword arguments and the double splat. A single splat (*) is basically used when you have an unknown number of arguments, and it is passed as array .

def with_args(*args)
  p args
end

with_args(1,2,"a")
# [1, 2, "a"]

The double splat (**) acts like the *, but for keyword arguments:

def with_args(**args)
  with_keyword(args)
end

def with_keyword(some_key: nil, other_key: nil)
  p "some_key: #{some_key}, other_key: #{other_key}"
end

with_args(some_key: "some_value", other_key: "other_value")
# "some_key: some_value, other_key: other_value"
with_args(some_key: "some_value")
# "some_key: some_value, other_key: "

In ruby, you can call a method without () and pass a hash without {} , so

with_args({some_key: "some_value", other_key: "other_value"})

is like writing

with_args some_key: "some_value", other_key: "other_value")

See this answer: What does a double * (splat) operator do and https://medium.freecodecamp.org/rubys-splat-and-double-splat-operators-ceb753329a78

So...

When writing

post users_path, params: { user: { name:  "",
                                   email: "user@invalid",
                                   password:              "foo",
                                   password_confirmation: "bar" } }

Is calls to process

process(:post, users_path, params: { user: { name:  "",
                                   email: "user@invalid",
                                   password:              "foo",
                                   password_confirmation: "bar" } }

Meaning in process , params are the hash

{ user: { name:  "",
  email: "user@invalid",
  password:              "foo",
  password_confirmation: "bar" } }

It doesn't matter the other keyword args of process, the hash is all params , all the other keywords are nil

Hope it makes sense...

Ah! Great question. This line:

class UsersSignupTest < ActionDispatch::IntegrationTest

means that the class is inheriting from ActionDispatch::IntegrationTest .

ActionDispatch::IntegrationTest is a Rails class. You're looking at the docs for the Net::HTTP class, which is a Ruby class.

Here's the API docs for the ActionDispatch::IntegrationTest methods.

Getting mixed up between Ruby and Rails is very common at the start. Rails is the framework, Ruby is the language.

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