我是Ruby和Sinatra的新手。我试图从HTML表单传递参数,并使用Sequel将它们插入PostgreSQL数据库(在Heroku上)。
与数据库的连接有效,因为我已成功使用此代码块
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
这很好用,但是我无法从HTML表单插入数据。数据未通过。
因此,例如,这不起作用
@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
错误消息是
Sequel :: DatabaseError at / PG ::错误:错误:列" email_address"不存在第1行:... sers(email_address,用户名,密码)VALUES(@email_addr ... ^
这导致我假设参数未通过
完整的代码是:
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>
非常感谢所有的帮助!
谢谢。
答案 0 :(得分:1)
摘要:由于您对Sequel的工作原理(以及Ruby的字符串插值的工作原理)存在误解,您的代码无效,因为您向数据库发送了无效的SQL。
<强>详情: 在使用Sequel库时,您几乎从不需要(也不应该)编写原始SQL代码。要更恰当地使用续集,请执行以下操作:
DB[:users] << {
email_address: params[:email_address],
username: params[:my_username],
password: params[:my_password]
}
或者这个:
DB[:users].insert( email_address:params[:email_address], … )
如果由于某种原因想要将这些存储为实例变量(你是在帖子的视图响应中使用它们的话吗?)那么:
@email = params[:email_address]
@user = params[:username]
@pass = params[:password]
DB[:users] << { email_address:@email, username:@user, password:@pass }
如果您真的想编写原始SQL,可以安全地使用占位符:
DB[
'INSERT INTO users (email_address,username,password) VALUES (?,?,?)',
params[:email_address],
params[:username],
params[:password],
]
这样做的好处是,它可以阻止用户在您的网站上执行SQL Injection Attack,例如说他们的用户名为bob','haha'); drop table users; select('
。 (想想如果将其放入两个INSERT
字符之间的正常'
语句中会发生什么。)
由于您的表单参数与您的列名称匹配,您甚至可以使用slicing your hash的自定义函数来实现这一点,例如。
DB[:users] << params.slice(:email_address,:username,:password)
阅读Sequel Documentation(例如Cheat Sheet),了解有关如何正确使用它的更多信息。
面向未来:
你的问题与Sinatra或参数无关,而只是你如何错误地使用Sequel。对于将来,要测试是否获取参数,您可以执行以下操作:
p params
并查看您的控制台(我假设您正在本地开发?)或者如果您在服务器上进行实时开发,则使用Heroku为您提供的任何日志记录功能(* shudder *)。或者,您甚至可以这样做:
post '/' do
params.inspect
end
,当您发布表单时,您会看到params
哈希中的内容。那么你就不会对错误的区域进行指责和调查。
答案 1 :(得分:1)
您正在尝试插入全局变量@email_address
,@username
和@password
,但尚未使用插值运算符#
您的SQL字符串为
INSERT INTO users (email_address, username, password) VALUES (@email_address, @username', @password)
当(除了杂散的单引号)之外,你的意思是让这些变量的值出现在命令中。你应该写一下
insert_ds = DB["INSERT INTO users (email_address, username, password)
VALUES (#@email_address, #@username, #@password)"]
通过添加
可以很容易地诊断出来puts insert_ds
直接分配后。