1

我是 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::Error: ERROR: column "email_address" does not exist LINE 1: ...sers (email_address, username, password) 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>

非常感谢所有的帮助!

谢谢你。

4

2 回答 2

1

摘要:由于误解了 Sequel 的工作原理(以及 Ruby 的字符串插值的工作原理),您的代码无法正常工作,因为您向数据库发送了无效的 SQL。

详细信息:在使用 Sequel 库时,您几乎不需要(也不应该)编写原始 SQL 代码。要更恰当地使用 Sequel,请执行以下操作:

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 注入攻击,例如通过说他们的用户名是bob','haha'); drop table users; select('. (想想如果你把它放在INSERT两个'字符之间的正常语句中会发生什么。)

由于您的表单参数与您的列名匹配,您甚至可以使用自定义函数来切片散列以使其更容易,例如

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

阅读Sequel 文档(例如Cheat Sheet)以获取有关如何正确使用它的更多信息。

未来

您的问题与 Sinatra 或参数无关,而只是您如何错误地使用 Sequel。对于将来,要测试您是否正在获取参数,您可以执行以下操作:

p params

并查看您的控制台(我假设您正在本地开发?)或者使用 Heroku 为您提供的任何日志记录功能,如果您在服务器上进行实时开发(*shudder*)。或者,您甚至可以这样做:

post '/' do
  params.inspect
end

当您发布表单时,您会看到params哈希中的确切内容。这样你就不会将责备和调查应用到错误的领域。

于 2013-05-09T00:56:56.197 回答
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

分配后直接。

于 2013-05-09T00:58:01.707 回答