Pregunta

I am using Ruby 1.8.7, trying to generate a string with the \' characteres, in order to create a script for running in MySQL. The result should be like this:

INSERT INTO table (name, description) values ('Joana d\'Arc', '')

But i can't get just one backslash in a ruby string. Using the following code:

string = "INSERT INTO table (name, description) values ('Joana d\\'Arc', '')"

I got the following string:

INSERT INTO table (name, description) values ('Joana d\\'Arc', '')

And with:

string = "INSERT INTO table (name, description) values ('Joana d\'Arc', '')"

I got this string:

INSERT INTO table (name, description) values ('Joana d'Arc', '')
¿Fue útil?

Solución

The reason puts works is that it shows what is actually in the string. The bare console is showing the string escaped. Try this on the console:

"Joana d\\'Arc".size

You will get back 12. If both backslashes were there you should get 13.

Hauleth's answer should work.

Otros consejos

I recommend avoiding writing raw SQL, and, in this age, I'd use an ORM, even for simple DB use. I highly recommend using the Sequel gem. Borrowing from an example in the Sequel docs:

sequel sqlite://temp
Your database is stored in DB...

Using SQLite, that started the sequel ORM in interactive mode, and created the SQLite database called "temp".

ruby-1.9.2-p290 :001 > require 'logger'
 => true 
ruby-1.9.2-p290 :002 > DB.loggers << Logger.new(STDOUT)
 => [#<Logger:0x0000010160bc40 @progname=nil, @level=0, @default_formatter=#<Logger::Formatter:0x0000010160bc18 @datetime_format=nil>, @formatter=nil, @logdev=#<Logger::LogDevice:0x0000010160bbc8 @shift_size=nil, @shift_age=nil, @filename=nil, @dev=#<IO:<STDOUT>>, @mutex=#<Logger::LogDevice::LogDeviceMutex:0x0000010160bba0 @mon_owner=nil, @mon_count=0, @mon_mutex=#<Mutex:0x0000010160bb50>>>>] 

That enabled logging so we can see what Sequel will do as it talks to the database.

ruby-1.9.2-p290 :003 > items = DB[:items] # Create a dataset
 => #<Sequel::SQLite::Dataset: "SELECT * FROM `items`"> 
ruby-1.9.2-p290 :004 > DB.tables
I, [2011-11-25T10:17:13.056311 #10130]  INFO -- : (0.000501s) SELECT * FROM `sqlite_master` WHERE (type = 'table' AND NOT name = 'sqlite_sequence')
 => [] 

Doh! I forgot to create the table...

ruby-1.9.2-p290 :005 > DB.create_table :items do
ruby-1.9.2-p290 :006 >       primary_key :id
ruby-1.9.2-p290 :007?>     String :name
ruby-1.9.2-p290 :008?>     Float :price
ruby-1.9.2-p290 :009?>   end
I, [2011-11-25T10:17:20.985851 #10130]  INFO -- : (0.002372s) CREATE TABLE `items` (`id` integer PRIMARY KEY AUTOINCREMENT, `name` varchar(255), `price` double precision)
 => nil 

The table is created.

ruby-1.9.2-p290 :010 > items = DB[:items] # Create a dataset
 => #<Sequel::SQLite::Dataset: "SELECT * FROM `items`"> 

That created a dataset, which is just a convenient way to talk to a table.

And, that's the payoff:

ruby-1.9.2-p290 :011 > items.insert(:name => "Joan d'Arc")
I, [2011-11-25T10:17:45.186945 #10130]  INFO -- : (0.001981s) INSERT INTO `items` (`name`) VALUES ('Joan d''Arc')
 => 1

The ORM automatically escapes the characters for you. Your job is simplified greatly.

ORMs are DBM aware, so they know when to escape for a particular database. Your code doesn't change. It's trivial to switch from SQLite to MySQL, Postgres, or even non-SQL databases.

Write it using %q{} notation

string = %q[INSERT INTO table (name, description) values ('Joanna d\\'Arc', '')]

You could try this:

string="INSERT INTO table (name, description) values ('Joana d"+"\\"+"'Arc','')"

I don't know if you must use 1.8.6, but if you can, update to 1.9.2. Its much faster and stabler, along with many more features.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top