【问题标题】:Why does ActiveResource Post not Send Any Parameters?为什么 ActiveResource Post 不发送任何参数?
【发布时间】:2011-09-26 05:08:31
【问题描述】:

我正在尝试使用 ActiveResource 和 Json 从 Rails3 客户端在 MongoDB/Sinatra 服务器中创建一个新的“用户”,并且发送的对象正文或哈希为空。在 Rails3 中,我创建了一个“用户”模型,并使用 Rails 控制台对 Sinatra 服务器进行了 ActiveResource 调用。服务器正确读取 URL,但似乎没有参数与对象一起传递。有人可以就我错过了什么或为什么我没有得到正确的输出给我他们的想法吗?

Sinatra 服务器使用 Ruby 1.8.7。
Rails3 客户端使用 Ruby 1.9.2。

来自 Rails3 客户端用户模型:

class User < ActiveResource::Base 
   self.site = "http://127.0.0.1:9393/"
   self.collection_name = "user/add"
   self.format = :json 
end

从 Rails3 控制台:

u=User.new(:first_name=>"Bill",:last_name=>"Smith")
=> #<User:0xa8d7fac @attributes={"first_name"=>"Bill", "last_name"=>"Smith"}, @prefix_options={}>
u.save
=> True

Sinatra 应用服务器接收以下对象(我使用“puts @app.inspect”从 Sinatra 服务器检索):

 #<Api:0xb6ee4e70 @block_params=[], @result={"status"=>200, "error"=>nil}, @params={}, @observer_state=true, @request=#<Sinatra::Request:0xb6ee4e0c @params={}, @route="/user/add.json", @env={"HTTP_HOST"=>"127.0.0.1:9393", "HTTP_ACCEPT"=>"*/*", "SERVER_NAME"=>"127.0.0.1", "REQUEST_PATH"=>"/user/add.json", "rack.url_scheme"=>"http", "HTTP_USER_AGENT"=>"Ruby", "REMOTE_HOST"=>"localhost", "CONTENT_LENGTH"=>"50", "rack.errors"=>#<Rack::Lint::ErrorWrapper:0xb6ee5294 @error=#<IO:0xb77e955c>>, "SERVER_PROTOCOL"=>"HTTP/1.1", "CONTENT_TYPE"=>"application/json", "rack.version"=>[1, 1], "rack.run_once"=>false, "SERVER_SOFTWARE"=>"WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)", "REMOTE_ADDR"=>"127.0.0.1", "PATH_INFO"=>"/user/add.json", "SCRIPT_NAME"=>"", "HTTP_VERSION"=>"HTTP/1.1", "rack.multithread"=>true, "rack.multiprocess"=>false, "REQUEST_URI"=>"http://127.0.0.1:9393/user/add.json", "rack.request.query_hash"=>{}, "SERVER_PORT"=>"9393", "REQUEST_METHOD"=>"POST", "rack.request.query_string"=>"", "rack.input"=>#<Rack::Lint::InputWrapper:0xb6ee52d0 @input=#<StringIO:0xb76fbeb0>>, "HTTP_CONNECTION"=>"close", "QUERY_STRING"=>"", "GATEWAY_INTERFACE"=>"CGI/1.1"}>, @original_params={}, @template_cache=#<Tilt::Cache:0xb6ee4fb0 @cache={}>, @env={"HTTP_HOST"=>"127.0.0.1:9393", "HTTP_ACCEPT"=>"*/*", "SERVER_NAME"=>"127.0.0.1", "REQUEST_PATH"=>"/user/add.json", "rack.url_scheme"=>"http", "HTTP_USER_AGENT"=>"Ruby", "REMOTE_HOST"=>"localhost", "CONTENT_LENGTH"=>"50", "rack.errors"=>#<Rack::Lint::ErrorWrapper:0xb6ee5294 @error=#<IO:0xb77e955c>>, "SERVER_PROTOCOL"=>"HTTP/1.1", "CONTENT_TYPE"=>"application/json", "rack.version"=>[1, 1], "rack.run_once"=>false, "SERVER_SOFTWARE"=>"WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)", "REMOTE_ADDR"=>"127.0.0.1", "PATH_INFO"=>"/user/add.json", "SCRIPT_NAME"=>"", "HTTP_VERSION"=>"HTTP/1.1", "rack.multithread"=>true, "rack.multiprocess"=>false, "REQUEST_URI"=>"http://127.0.0.1:9393/user/add.json", "rack.request.query_hash"=>{}, "SERVER_PORT"=>"9393", "REQUEST_METHOD"=>"POST", "rack.request.query_string"=>"", "rack.input"=>#<Rack::Lint::InputWrapper:0xb6ee52d0 @input=#<StringIO:0xb76fbeb0>>, "HTTP_CONNECTION"=>"close", "QUERY_STRING"=>"", "GATEWAY_INTERFACE"=>"CGI/1.1"}, @app=nil, @observer_peers=[#<HookMongo:0xb6d714f8 @extra=nil, @app=#<Api:0xb6ee4e70 ...>>], @response=#<Sinatra::Response:0xb6edb94c @writer=#<Proc:0xb77cd4b0@/home/scott/.rvm/gems/ruby-1.8.7-p334@api/gems/rack-1.3.0/lib/rack/response.rb:28>, @block=nil, @chunked=false, @length=0, @header={"Content-Type"=>nil}, @body=[], @status=200>>

如您所见,@params={} 为空。

使用 HTTP 请求有效:

Net::HTTP.post_form(URI.parse('http://127.0.0.1:9393/user/add.json'),{'first_name' => 'Smith', 'last_name' => 'Bill'})

并产生这个:

#<Api:0xb6ee4fec @block_params=[], @result={"status"=>200, "error"=>nil}, @params={"last_name"=>"Bill", "first_name"=>"Smith"}, @observer_state=true, @request=#<Sinatra::Request:0xb6ee4f88 @params={"last_name"=>"Bill", "first_name"=>"Smith"}, @route="/user/add.json", @env={"HTTP_HOST"=>"127.0.0.1:9393", "HTTP_ACCEPT"=>"*/*", "SERVER_NAME"=>"127.0.0.1", "REQUEST_PATH"=>"/user/add.json", "rack.url_scheme"=>"http", "HTTP_USER_AGENT"=>"Ruby", "REMOTE_HOST"=>"localhost", "CONTENT_LENGTH"=>"31", "rack.errors"=>#<Rack::Lint::ErrorWrapper:0xb6ee5410 @error=#<IO:0xb77e955c>>, "SERVER_PROTOCOL"=>"HTTP/1.1", "CONTENT_TYPE"=>"application/x-www-form-urlencoded", "rack.version"=>[1, 1], "rack.run_once"=>false, "SERVER_SOFTWARE"=>"WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)", "REMOTE_ADDR"=>"127.0.0.1", "PATH_INFO"=>"/user/add.json", "SCRIPT_NAME"=>"", "HTTP_VERSION"=>"HTTP/1.1", "rack.multithread"=>true, "rack.request.form_vars"=>"first_name=Smith&last_name=Bill", "rack.multiprocess"=>false, "REQUEST_URI"=>"http://127.0.0.1:9393/user/add.json", "rack.request.form_input"=>#<Rack::Lint::InputWrapper:0xb6ee544c @input=#<StringIO:0xb76d72a4>>, "rack.request.query_hash"=>{}, "SERVER_PORT"=>"9393", "REQUEST_METHOD"=>"POST", "rack.request.form_hash"=>{"last_name"=>"Bill", "first_name"=>"Smith"}, "rack.request.query_string"=>"", "rack.input"=>#<Rack::Lint::InputWrapper:0xb6ee544c @input=#<StringIO:0xb76d72a4>>, "QUERY_STRING"=>"", "GATEWAY_INTERFACE"=>"CGI/1.1"}>, @original_params={"last_name"=>"Bill", "first_name"=>"Smith"}, @template_cache=#<Tilt::Cache:0xb6ee512c @cache={}>, @env={"HTTP_HOST"=>"127.0.0.1:9393", "HTTP_ACCEPT"=>"*/*", "SERVER_NAME"=>"127.0.0.1", "REQUEST_PATH"=>"/user/add.json", "rack.url_scheme"=>"http", "HTTP_USER_AGENT"=>"Ruby", "REMOTE_HOST"=>"localhost", "CONTENT_LENGTH"=>"31", "rack.errors"=>#<Rack::Lint::ErrorWrapper:0xb6ee5410 @error=#<IO:0xb77e955c>>, "SERVER_PROTOCOL"=>"HTTP/1.1", "CONTENT_TYPE"=>"application/x-www-form-urlencoded", "rack.version"=>[1, 1], "rack.run_once"=>false, "SERVER_SOFTWARE"=>"WEBrick/1.3.1 (Ruby/1.8.7/2011-02-18)", "REMOTE_ADDR"=>"127.0.0.1", "PATH_INFO"=>"/user/add.json", "SCRIPT_NAME"=>"", "HTTP_VERSION"=>"HTTP/1.1", "rack.multithread"=>true, "rack.request.form_vars"=>"first_name=Smith&last_name=Bill", "rack.multiprocess"=>false, "REQUEST_URI"=>"http://127.0.0.1:9393/user/add.json", "rack.request.form_input"=>#<Rack::Lint::InputWrapper:0xb6ee544c @input=#<StringIO:0xb76d72a4>>, "rack.request.query_hash"=>{}, "SERVER_PORT"=>"9393", "REQUEST_METHOD"=>"POST", "rack.request.form_hash"=>{"last_name"=>"Bill", "first_name"=>"Smith"}, "rack.request.query_string"=>"", "rack.input"=>#<Rack::Lint::InputWrapper:0xb6ee544c @input=#<StringIO:0xb76d72a4>>, "QUERY_STRING"=>"", "GATEWAY_INTERFACE"=>"CGI/1.1"}, @app=nil, @observer_peers=[#<HookMongo:0xb6d68c18 @extra=nil, @app=#<Api:0xb6ee4fec ...>>], @response=#<Sinatra::Response:0xb6edbac8 @writer=#<Proc:0xb77cd4b0@/home/scott/.rvm/gems/ruby-1.8.7-p334@api/gems/rack-1.3.0/lib/rack/response.rb:28>, @block=nil, @chunked=false, @length=0, @header={"Content-Type"=>nil}, @body=[], @status=200>>

@params={"last_name"=>"Bill", "first_name"=>"Smith"} 不再为空。

在 active_resource/connection.rb 文件中,第 94 行

# Executes a POST request.
# Used to create new resources.
def post(path, body = '', headers = {})
  with_auth { request(:post, path, body.to_s, build_request_headers(headers, :post, self.site.merge(path))) }
end

我确定我遗漏了一些东西,但这似乎创造了一个空的身体。

提前感谢您的建议。

【问题讨论】:

    标签: ruby-on-rails sinatra activeresource


    【解决方案1】:

    默认情况下,Sinatra 不解析正文。如果有表单编码标头,Rack 将解析表单编码主体并将其放入参数中,这就是使用post_form 的原因。您需要将请求正文拉出并自己解析。例如

    post '/add' do
      user_hash = JSON.parse request.body
      User.create! user_hash
    end
    

    【讨论】:

    • 谢谢。这解决了问题。就像我想的那样,它是 Sinatra 而不是 Activeresource。对于任何想要了解 Sinatra 请求对象的人,您可以在"Accessing the Request Object" 下找到它。我使用的具体代码是:coderequest_body=JSON.parse request.body.read。
    • 正如 Scott 已经提到的,您必须使用 request.body.read,因为主体不是简单的字符串,而是 StringIO 类的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 2017-07-06
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多