0

I have coded a Ruby IRC bot which is on github (/ninjex/rubot) which is having some conflicting output with MySQL on a dedicated server I just purchased.

Firstly we have the connection to the database in the MySQL folder (in .gitignore) which looks similar to the following code block.

@con = Mysql.new('localhost', 'root', 'pword', 'db_name')

Then we have an actual function to query the database

def db_query
 que = get_message # Grabs query from user i.e,./db_query SELECT * FROM words
 results = @con.query(que) # Send query through the connection i.e, @con.query("SELECT * FROM WORDS")
 results.each {|x| chan_send(x)} # For each row returned, send it to the channel via
end

On my local machine, when running the command:

./db_query SELECT amount, user from words WHERE user = 'Bob' and word = 'hello'

I receive the output in IRC in an Array like fashion: ["17", "Bob"] Where 17 is amount and Bob is the user.

However, using this same function on my dedicated server results in an output like: 17Bob I have attempted many changes in the code, as well as try to parse the data into it's own variable, however it seems that 17Bob is coming out as a single variable, making it impossible to parse into something like an array, which I could then use to send the data correctly.

This seems odd to me on both my local machine and the dedicated server, as I was expecting the output to first send 17 to the IRC and then Bob like:

17
Bob

For all the functions and source you can check my github /Ninjex/rubot, however you may need to install some gems.

Singularity
  • 271
  • 2
  • 11
  • I created a pull request, https://github.com/Ninjex/Rubot/pull/1, for you that exposes some ruby idioms that you can use to simplify your code. It is not entirely on topic but should encourage you to explore the standard library a little more. – Matt Dressel Jan 09 '14 at 16:59
  • Yeah, most of the idioms I was not familiar with upon first coding in Ruby. I'll admit I started this project when Ruby was new to me and I came from programming heavy in PHP. I however, did not know that Ruby didn't need a return keyword, nice. Thanks for all your help, I look forward to fixing up a lot of excess code and converting over to mysql2 this weekend. – Singularity Jan 09 '14 at 22:26
  • Hit me up if you have any more questions. I would be glad to point you in the right direction. – Matt Dressel Jan 10 '14 at 15:42
  • I can not thank you enough for your help throughout this process! I feel like an idiot, I finally found the resulting issue. I had updated my Ruby version on the dedicated server, but I managed to slip up and not configure it to use the latest install, so it was running 1.08 instead of 1.9.3 Once I changed the settings, it worked like a charm. I am very grateful for your help. Is there a way I could contact you about small questions to push me further in programming to become a better programmer. Thank you for all your time an patience! – Singularity Jan 13 '14 at 15:45
  • I opened a chat room for us. Let me know if that works. – Matt Dressel Jan 13 '14 at 16:20

1 Answers1

1

A few notes:

  1. Make sure you are sanitizing query via get_message. Or you are opening yourself up to some serious security problems.
  2. Ensure you are using the same versions of the mysql gem, ruby and MySql. Differences in any of these may alter the expected output.
  3. If you are at your wits end and are unable to resolve the underlying issue, you can always send a custom delimiter and use it to split. Unfortunately, it will muck up the case that is actually working and will need to be stripped out.

Here's how I would approach debugging the issue on the dedicated machine:

def db_query
 que = get_sanitized_message
 results = @con.query(que)
 require 'pry'
 binding.pry

 results.each {|x| chan_send(x)}
end
  1. Add the pry gem to your Gemfile, or gem install pry.
  2. Update your code to use pry: see above
  3. This will open up a pry console when the binding.pry line is hit and you can interrogate almost everything in your running application.
  4. I would take a look at results and see if it's an array. Just type results in the console and it will print out the value. Also type out results.class. It's possible that query is returning some special result set object that is not an array, but that has a method to access the result array.
  5. If results is an array, then the issue is most likely in chan_send. Perhaps it needs to be using something like puts vs print to ensure there's a new line after each message. Is it possible that you have different versions of your codebase deployed? I would also add a sleep 1 within the each block to ensure that this is not related to your handling of messages arriving at the same time.
Matt Dressel
  • 2,194
  • 16
  • 18
  • Thanks, I actually have this specific command (db_query) as an admin function which is restricted for only my use. get_message actually pulls from another function called send_data which strips all kinds of *lines (g, k, b, etc). Everything is sanitized well or restricted accordingly. It had been brought to my attention that my local machine is 32bit while the dedicated is 64bit. When in an interactive ruby session, however both produce output as I would except normally. I will be sure to check all the versions of each install. Still very odd imo. – Singularity Jan 09 '14 at 15:17
  • Okay, I tried the above: ``[1] pry(main)> results.class => Mysql::Result`` ``[2] pry(main)> results => #`` I knew the query ends up as a Mysql::Result and not an actual Array. The way to echo out the data is via ``result.each{|row| puts row}`` or similar. sleeping isn't helping neither. I even tried making a new variable and concatenating the values in the result to this variable separated via commas with no luck. It's just interpreted as on value even though it's from two rows. Hmph... – Singularity Jan 09 '14 at 15:36
  • Which mysql gem are you using? Looks like you can have query return an array by using: `:as => :array`. Check out: https://github.com/brianmario/mysql2#usage – Matt Dressel Jan 09 '14 at 15:41
  • So, what's the output of `result.each{|row| puts row}`? Row should be an array and both values will be sent to the channel at the same time. In order to send each individually, you need to iterate over the row via `row.each`. – Matt Dressel Jan 09 '14 at 15:46
  • ``result.each{|row| puts row}`` is sending to the terminal and is actually sending each for value separated via new line feeds. So the issue may lie within chan_send, but this function never manipulates the text, it simply pushes the data through the socket to IRC. I am using the default gem which comes with the installation by default. However, I may look into mysql2 as this seems like a much better alternative and more versatile. – Singularity Jan 09 '14 at 15:52
  • chan_send function: https://github.com/Ninjex/Rubot/blob/master/functions/chan_send.rb send_data function: https://github.com/Ninjex/Rubot/blob/master/functions/send_data.rb As you can see the only manipulation that would occur is if the message is flagged inside the filter list or spam. – Singularity Jan 09 '14 at 16:01
  • 1. I haven't used mysql in a couple years, but `mysql2` was definitely the improved gem. 2. Puts of a 2-element array will print as two separate rows. Make sure this is not clouding your assessment. – Matt Dressel Jan 09 '14 at 16:34