Weird assignment problem, very confused :(

Hey, I have the following line in my controller:

User.create(:email => “[email protected]”, :password =>
‘asldfkjadsfadsf’, :ip => request.remote_ip)

my IP is 127.0.0.1 - now User.find_by_ip(‘127.0.0.1’) returns 0
records although User.first contains ‘127.0.0.1’

if I change it to:

User.create(:email => “[email protected]”, :password =>
‘asldfkjadsfadsf’, :ip => ‘127.0.0.1’)
the finder returns the record

The model is a devise model, ip is attr_accessible
Can anyone please help me getting out of this confusion? I don’t
understand it

This is really weird, either a bug (it’s 3.1 rc5) or I don’t know:

  1. DocType.create(:name => request.remote_ip)
    DocType.find_by_name(‘127.0.0.1’)
    DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types” WHERE
    “doc_types”.“name” = ‘127.0.0.1’ LIMIT 1
    => nil

DocType.create(:name => “127.0.0.1”)
DocType.find_by_name(‘127.0.0.1’)
DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types” WHERE
“doc_types”.“name” = ‘127.0.0.1’ LIMIT 1
=> #<DocType id: 3, name: “127.0.0.1”, description: nil>

On Aug 29, 6:34pm, sol [email protected] wrote:

This is really weird, either a bug (it’s 3.1 rc5) or I don’t know:

  1. DocType.create(:name => request.remote_ip)
    DocType.find_by_name(‘127.0.0.1’)
    DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types” WHERE
    “doc_types”.“name” = ‘127.0.0.1’ LIMIT 1
    => nil

So what’s actually in the database in that case? Any unexpected
characters (new lines etc.) ?

Fred

What does User.first.ip.inspect return in the two cases?

how can I get more details about the encoding/chars in the dbconsole?

sqlite> select name from doc_types;
127.0.0.1
127.0.0.1

On 29 Aug., 20:02, Frederick C. [email protected]

inspect returns:

ruby-1.9.2-p180 :009 > DocType.all.map {|d| d.name.inspect}
DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types”
=> ["“127.0.0.1"”, "“127.0.0.1"”]

and as above find only returns on of them (the one using
request.remote_ip

the output for the above lines is:

String
127.0.0.1 (.ip)
127.0.0.1 (.ip.to_s)
127.0.0.1 “#{d.ip}”
“127.0.0.1” ip.inspect

no idea what this could be else… the size is 9 in all examples

Quoting sol [email protected]:

This is really weird, either a bug (it’s 3.1 rc5) or I don’t know:

  1. DocType.create(:name => request.remote_ip)
    DocType.find_by_name(‘127.0.0.1’)
    DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types” WHERE
    “doc_types”.“name” = ‘127.0.0.1’ LIMIT 1
    => nil

Dynamic typing is wonderful, until it isn’t. My hypothesis is that
remote_ip
is not a Fixnum or Bignum but a custom class that overrides to_s. To
test the
hypothesis, I’d run the following in the console of writing to the log.

puts request.remote_ip.class
puts request.remote_ip
puts request.remote_ip.to_s
puts “#{request.remote_ip}”
puts request.remote_ip.inspect

DocType.create(:name => request.remote_ip)
DocType.last
DocType.create(:name => request.remote_ip.to_s)
DocType.last

Somewhere in this, I expect the truth will be revealed.

A IPv4 address is a 32 bit, unsigned number. It is usually
represented/rendered in dotted quad notation, but 0x7F000001 or
2130706433 are
equally valid representations of the local or loopback interface’s IPv4
address.

HTH,
Jeffrey

Christoph B. wrote in post #1019055:

Hey, I have the following line in my controller:

User.create(:email => “[email protected]”, :password =>
‘asldfkjadsfadsf’, :ip => request.remote_ip)

now User.find_by_ip(‘127.0.0.1’) returns 0
records

if I change it to:

User.create(:email => “[email protected]”, :password =>
‘asldfkjadsfadsf’, :ip => ‘127.0.0.1’)
the finder returns the record

That seems like definitive proof that:

request.remote_ip != ‘127.0.0.1’

In fact you could test that:

if request.remote_ip == ‘127.0.0.1’
puts ‘yes’
else
puts ‘no’
end

inspect returns:

ruby-1.9.2-p180 :009 > DocType.all.map {|d| d.name.inspect}
DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types”
=> ["“127.0.0.1"”, "“127.0.0.1"”]

The output shows that the string is actually “127.0.0.1”–not 127.0.0.1.
For example:

data = [
%q{“127.0.0.1”},
%q{127.0.0.1}
]

data.each do |str|
p str
end

–output:–
"“127.0.0.1"”
“127.0.0.1”

See the difference?

I am sorry, Christoph, but from your post it is not clear, how you
create a record with :ip => request.remote_ip

You probably cannot do this in console (request.remote_ip not defined),
so you’ll have to test it all in controller.

Can you do it in 3 steps:

  1. create two records in the database (with a string and with
    request.remote_ip ),
  2. see what is in the database (there is, for example, a firefox
    extension to browse an sqlite database),
  3. verify in console that the records look identical, but find_by_ip
    returns only one?

This is what i would do.

Alexey.

7stud – wrote in post #1019114:

inspect returns:

ruby-1.9.2-p180 :009 > DocType.all.map {|d| d.name.inspect}
DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types”
=> ["“127.0.0.1"”, "“127.0.0.1"”]

The output shows that the string is actually “127.0.0.1”–not 127.0.0.1.

I disagree, this output shows only that the inspect of the string is
(unquoted) “127.0.0.1”, but the string itself is (unquoted) 127.0.0.1.
So this does not clarify the issue.

Alexey.

This is strange, given that request.remote_ip.class returns String.
What if you use request.remote_ip.to_s instead of
request.remote_ip everywhere?

If this does not fix it, than it looks like a bug to me.

I also have an application where i store IP addresses, but i didn’t try
yet to find by ip, and the IP returned by request.remote_ip looked
like a string to me.
I would be interested to understand what’s the difference.

I found out with sqlite’s ‘dump’ why it does not work, here is the
full thing:

it seems its in a different representation, now I am not sure if this
is a rails bug or what to do with it

Christophe,
I have just tested my application: i use request.remote_ip, and
find_by_ip('127.0.0.1') works for me.
If you describe a minimal example how to reproduce your problem, i can
try to test it.

I use rails 3.1rc6 and ruby 1.9.2

Alexey.

I also use sqlite in development, this is from my Gemfile:

group :development do
gem ‘sqlite3’
end

On Aug 30, 9:07am, sol [email protected] wrote:

I found out with sqlite’s ‘dump’ why it does not work, here is the
full thing:

gist:9fa01f6d150c3be6bd04 · GitHub

it seems its in a different representation, now I am not sure if this
is a rails bug or what to do with it

That byte sequence is in fact exactly the same as 127.0.0.1 (if you
encoding is ascii or anything that agrees with ascii for the lower 7
bits). For me this points at an encoding problem, but I’m not sure why
this would happen. You might try sticking some breakpoints in the
active record code to see what the difference is (or check if the ruby
encoding of the two strings you have differ)

Fred

Thanks a lot for the efforts!

The example should be in the gist I posted above, thats exactly what I
am doing
However, which database are you using? It is sqlite for me, and I
think it might be the sqlite driver

Thanks a lot Alexey, very helpful!

I’ve opened a bug but I’m not sure if it is rails or sqlite3 related:

so I also opened it in sqlite3:

I confirm that there is a problem.
This is with Rails 3.1.0rc8

$ rails new test_ip
$ cd test_ip
$ rails generate model MyModel ip:string description:string
$ rake db:migrate
$ rails generate controller Writer write_records

app/controllers/writer_controller.rb:

class WriterController < ApplicationController
def write_records
MyModel.create!(:ip => request.remote_ip, :description => ‘request’)
MyModel.create!(:ip => ‘127.0.0.1’, :description => ‘string’)
end
end

$ rails s

go to
http://localhost:3000/writer/write_records

$ rails c

MyModel.all
MyModel Load (0.2ms) SELECT “my_models”.* FROM “my_models”
=> [#<MyModel id: 1, ip: “127.0.0.1”, description: “request”,
created_at: “2011-08-30 09:42:09”, updated_at: “2011-08-30 09:42:09”>,
#<MyModel id: 2, ip: “127.0.0.1”, description: “string”, created_at:
“2011-08-30 09:42:09”, updated_at: “2011-08-30 09:42:09”>]

MyModel.where(:ip => ‘127.0.0.1’).all
MyModel Load (0.2ms) SELECT “my_models”.* FROM “my_models” WHERE
“my_models”.“ip” = ‘127.0.0.1’
=> [#<MyModel id: 2, ip: “127.0.0.1”, description: “string”,
created_at: “2011-08-30 09:42:09”, updated_at: “2011-08-30 09:42:09”>]

MyModel.first.ip == ‘127.0.0.1’
MyModel Load (0.2ms) SELECT “my_models”.* FROM “my_models” LIMIT 1
=> true

In the database for the first ip i have: X’3132372E302E302E31’

Alexey M. wrote in post #1019158:

7stud – wrote in post #1019114:

inspect returns:

ruby-1.9.2-p180 :009 > DocType.all.map {|d| d.name.inspect}
DocType Load (1.4ms) SELECT “doc_types”.* FROM “doc_types”
=> ["“127.0.0.1"”, "“127.0.0.1"”]

The output shows that the string is actually “127.0.0.1”–not 127.0.0.1.

I disagree,

Okay, I agree with your disagree. I have no idea what this means,
though:

this output shows only that the inspect of the string is
(unquoted) “127.0.0.1”, but the string itself is (unquoted) 127.0.0.1.
So this does not clarify the issue.

Alexey.

strings = [
“abc”,
%q(“abc”)
]

results = strings.map do |str|
str.inspect
end

p results

results.each do |str|
puts str
end

–output:–
["“abc”", “”\“abc\”""]
“abc”
““abc””

The second element in the array is hard to interpret: if you strip away
what inspect added to the first string, you get:

\“abc\”

I guess \ is a literal slash and ’ is an escaped quote.