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', '')
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With