简体   繁体   English

Ruby与Sequel和Sinatra:表单参数传递

[英]Ruby with Sequel and Sinatra: form parameter passing

I am new to Ruby and Sinatra. 我是Ruby和Sinatra的新手。 I am attempting to pass parameters from an HTML form and insert them into a PostgreSQL database (on Heroku) with Sequel. 我正在尝试通过HTML表单传递参数,并将它们插入到带有Sequel的PostgreSQL数据库(在Heroku中)中。

The connection to the database works because I have succeeded with this code block 与数据库的连接有效,因为我已成功使用此代码块

DB = Sequel.connect(connection_ credentials)

insert_ds = DB["INSERT INTO users (email_address, username, password) VALUES ('email@email.com', 'my_username', 'my_password')"]
insert_ds.insert

This works fine, but I cannot insert data from an HTML form. 这工作正常,但我无法从HTML表单插入数据。 The data is not being passed. 数据未传递。

So, for example, this does not work 因此,例如,这不起作用

@email_address = params[:email_address]
@username = params[:username]
@password = params[:password]

insert_ds = DB["INSERT INTO users (email_address, username, password) VALUES (@email_address, @username', @password)"]
insert_ds.insert

The error message is 错误消息是

Sequel::DatabaseError at / PG::Error: ERROR: column "email_address" does not exist LINE 1: ...sers (email_address, username, password) VALUES (@email_addr... ^ / PG :: Error处的Sequel :: DatabaseError:错误:列“ email_address”不存在LINE 1:... sers(电子邮件地址,用户名,密码)值(@email_addr ... ^

which leads me to presume that the parameter was not passed 这导致我推测该参数未传递

The full code is: 完整的代码是:

require 'sinatra'
require "rubygems"
require "sequel"
require 'sinatra/sequel'
require 'pg'

DB = Sequel.connect('postgres://my username:my password@ec2-54-243-250-125.compute-1.amazonaws.com:5432/d70h0792oqobc')

get '/' do
  #@users = users.all :order => :id.desc
  #@title = 'All Users'
  erb :index
end

post '/' do
    @email_address = params[:email_address]
    @username = params[:username]
    @password = params[:password]
    insert_ds = DB["INSERT INTO users (email_address, username, password) VALUES (@email_address, @username, @password)"]
    insert_ds.insert
    redirect '/'
end


__END__

@@ layout
<!DOCTYPE html>
<html>
<head></head>
<body>
<%= yield %>
</body>
</html>

@@index
<section id="add">
  <form action="/" method="post">
  <label class="label"> <span>Email Address: </span> </label> <input type="text" id="email_address" name="email_address" />
  <label class="label"> <span>Username: </span> </label> <input type="text" id="username" name="username" />
  <label class="label"> <span>Password: </span> </label> <input type="password" id="password" name="password" />
    <input type="submit" value="Register me!">
  </form>
</section>

Very grateful for all help! 非常感谢所有帮助!

Thank you. 谢谢。

Summary : Your code wasn't working because you were sending invalid SQL to the database, due to a misunderstanding of how Sequel works (and how Ruby's string interpolation works). 简介 :由于对Sequel的工作方式(以及Ruby的字符串插值的工作方式)有误解,您的代码无法正常工作是因为您向数据库发送了无效的SQL。

Details : You almost never need to (nor should you) write raw SQL code when using the Sequel library. 详细信息 :使用Sequel库时,几乎不需要(也不需要)编写原始SQL代码。 To use Sequel more appropriately, do this: 若要更适当地使用Sequel,请执行以下操作:

DB[:users] << {
  email_address: params[:email_address],
  username:      params[:my_username],
  password:      params[:my_password]
}

or this: 或这个:

DB[:users].insert( email_address:params[:email_address], … )

If you want to store these as instance variables for some reason (you're using them in a view response for the post?) then: 如果您出于某种原因想要将它们存储为实例变量(您正在帖子的视图响应中使用它们?),则:

@email = params[:email_address]
@user  = params[:username]
@pass  = params[:password]
DB[:users] << { email_address:@email, username:@user, password:@pass }

If you really want to write raw SQL, you can use placeholders safely like so: 如果您确实想编写原始SQL,则可以安全地使用占位符,如下所示:

DB[
  'INSERT INTO users (email_address,username,password) VALUES (?,?,?)',
  params[:email_address],
  params[:username],
  params[:password],
]

The benefit of this is that it prevents users from performing a SQL Injection Attack on your site, for example by saying that their username is bob','haha'); drop table users; select(' 这样做的好处是可以防止用户在您的站点上执行SQL注入攻击 ,例如说用户名是bob','haha'); drop table users; select(' bob','haha'); drop table users; select(' bob','haha'); drop table users; select(' . (Think about what happens if you put that into a normal INSERT statement between two ' characters.) bob','haha'); drop table users; select('(想想如果将其放入两个'字符之间的普通INSERT语句中会发生什么。)

Since your form parameters match your column names, you can even use a custom function for slicing your hash to make this even easier, eg 由于您的表单参数与列名匹配,因此您甚至可以使用自定义函数对哈希进行切片,以使其变得更加容易,例如

DB[:users] << params.slice(:email_address,:username,:password)

Read the Sequel Documentation (eg the Cheat Sheet ) for more information on how to properly use it. 阅读续集文档 (例如备忘单 )以获取有关如何正确使用它的更多信息。

For the Future : 为了未来

Your problem was unrelated to Sinatra or parameters, but simply how you were incorrectly using Sequel. 您的问题与Sinatra或参数无关,而仅仅是您如何错误地使用Sequel。 For the future, to test if you are getting your parameters, you can do: 为了将来测试获取的参数,可以执行以下操作:

p params

and look at your console (I assume you are developing locally?) or else use whatever logging capabilities Heroku gives you if you are developing live on the server (*shudder*). 并查看您的控制台(假设您正在本地开发?),或者如果您正在服务器上实时开发(* shudder *),则使用Heroku提供的任何日志记录功能。 Alternatively, you can even do: 另外,您甚至可以执行以下操作:

post '/' do
  params.inspect
end

and you will see, when you post the form, exactly what is in the params hash. 当您发布表单时,您将看到params哈希中的确切内容。 Then you won't apply blame and investigation to the wrong area. 这样一来,您就不会对错误的地区进行指责和调查。

You are trying to interpolate the global variables @email_address , @username , and @password but haven't used the interpolation operator # 您正在尝试对全局变量@username @email_address@username @email_address@password进行插值,但尚未使用插值运算符#

Your SQL string apears as 您的SQL字符串显示为

INSERT INTO users (email_address, username, password) VALUES (@email_address, @username', @password)

when (apart from the stray single quote) you mean to have the values of those variables appear within the command. 何时(除了流浪单引号之外),您的意思是使这些变量的出现在命令中。 You should write instead 你应该写

    insert_ds = DB["INSERT INTO users (email_address, username, password)
                               VALUES (#@email_address, #@username, #@password)"]

It is easy to diagnose this by adding 通过添加很容易诊断

puts insert_ds

directly after the assignment. 分配后直接进行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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