【问题标题】:How does the post method work in Ruby on Railspost 方法在 Ruby on Rails 中如何工作
【发布时间】:2019-05-16 13:58:33
【问题描述】:

我来自 Python 和 Java 背景,只有 CSS、HTML、Ruby 的基本知识,并尝试学习使用 Ruby on Rails 进行 Web 开发。我正在尝试按照Michael Hartl 上的教程进行操作。我不明白代码清单 7.23 中的 post 方法在做什么参数。

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

从我在API 中跟踪的内容来看,它接受了两个非可选参数,它们都是字符串,但在清单7.23 中,第二个参数中突然出现了一个散列语法params:,这让我感到困惑。谁能赐教?

【问题讨论】:

    标签: ruby-on-rails ruby post


    【解决方案1】:

    我认为你看错地方了,链接显示http.post。你想要IntegrationTest post

    发件人:https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/testing/integration.rb

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

    还有:

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

    编辑:双响

    Ruby 2.0 添加了关键字参数双 splat。 当您有未知数量的参数时,基本上使用单个 splat (*),它作为 array 传递。

    def with_args(*args)
      p args
    end
    
    with_args(1,2,"a")
    # [1, 2, "a"]
    

    双 splat (**) 的作用类似于 *,但用于关键字参数:

    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: "
    

    在 ruby​​ 中,您可以调用不带() 的方法并传递不带{} 的哈希,所以

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

    就像写作

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

    看到这个答案:What does a double * (splat) operator dohttps://medium.freecodecamp.org/rubys-splat-and-double-splat-operators-ceb753329a78

    所以...

    写作时

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

    是调用过程

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

    processparams 中的含义是哈希

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

    process的其他关键字args无所谓,hash都是params,其他关键字都是nil

    希望这是有道理的......

    【讨论】:

    • 嗨,您能告诉我对process 的方法调用是如何工作的吗?我已经在上面的答案中解释了我的一些思考过程,但我无法从教程的上下文中完全掌握它。
    • @PrashinJeevaganth 当然可以。我使用双 splat (**) 语法以及调用传递给进程的方式编辑了答案。
    • 如果我错了,请纠正我。通过断言,我们使用没有错误消息的那个,User.count 被评估两次,一次在开始时,然后在执行代码块后第二次,这是 post 函数,它具有一些哈希参数,如中所述这个答案。 post 可能会由于 process 而返回一些东西,但也可能会更新计数,因此我们希望控制台在实际存在差异时发出“红色”声音。不太确定断言的实现在做什么,但这是我最好的选择。
    • @PrashinJeevaganth 你是正确的,User.count 被评估了两次。但测试是检查数字是否保持不变,因为它是一个post 请求来创建一个 invalid 用户。如果post 请求会更新计数,这是一个错误,测试应该会失败。如果你看一下实现,你会看到assert_no_difference 只是用0 调用assert_difference。实现是:assert_differenceapidock.com/rails/ActiveSupport/Testing/Assertions/…
    • 我其实被这个弄糊涂了:post :create, article: invalid_attributes in assert_no_difference , :something 通常意味着我们已经预先定义了一个hash 并且想要访问对应键的值,但是你在哪里找到:create,因为它是一种方法而不是某种密钥? article 也有同样的困惑。我只是通过阅读名称将其解释为您提到的内容,但我无法真正解释代码实现。
    【解决方案2】:

    啊!好问题。这一行:

    class UsersSignupTest &lt; ActionDispatch::IntegrationTest

    表示该类继承自ActionDispatch::IntegrationTest

    ActionDispatch::IntegrationTest 是一个 Rails 类。您正在查看 Net::HTTP 类的文档,这是一个 Ruby 类。

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

    在开始时混淆 Ruby 和 Rails 是很常见的。 Rails 是框架,Ruby 是语言。

    【讨论】:

    • 嗨,感谢您的回复,实际上我对我必须研究的 API 数量感到很困惑(Rails、Ruby、HTTP、HTML、CSS)。通常我只是被教程难住了,我不知道他们是在重写现有的类方法还是从无到有地实现一个新方法。
    • 哦,它比我的答案更具可读性,我只是看了 github :)
    • 而且我实际上也不理解API,如您之前的答案所示,根据我的基本理解,我认为post(path,**args) 中的**args 确实意味着需要传入一个哈希,并且相同的哈希被传递到process,但是当process 中有这么多关键字参数并且我看不到哈希中包含的键值对如何映射到参数时,问题就出现了.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多