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

时间:2013-05-09 00:26:15

标签: ruby sinatra sequel

我是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>

非常感谢所有的帮助!

谢谢。

2 个答案:

答案 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

直接分配后。