Putting ~ after id fetches record - ruby-on-rails

If we have an Active Record database say Users
User.find(id) works as expected:
But so does User.find('id~')
Also User.find('id~gibberish')
Is this a vulnerability or flaw of ActiveRecord?
How do I handle such requests appropriately?

This should help clear some things up, it is not ActiveRecord, it's Ruby's to_i method that you're seeing.
2.2.1 :001 > '11'.to_i
=> 11
2.2.1 :002 > '11~'.to_i
=> 11
2.2.1 :003 > '11~gibberish'.to_i
=> 11
This is not a vulnerability nor a flaw. If you're worried about input like this, I'd ask for an example where you think it could cause you harm.
Additionally if you'd like to be super defensive, use Integer(
2.2.1 :004 > Integer('11~gibberish')
ArgumentError: invalid value for Integer(): "11~gibberish"
2.2.1 :005 > Integer('11')
=> 11

Related

Difference between Ruby’s Hash and ActiveSupport’s HashWithIndifferentAccess

What is the difference between Ruby’s Hash and ActiveSupport’s HashWithIndifferentAccess? Which is the best for dynamic hashes?
Below is the simple example that will show you difference between simple ruby hash & a "ActiveSupport::HashWithIndifferentAccess"
HashWithIndifferentAccess allows us to access hash key as a symbol or string
Simple Ruby Hash
$ irb
2.2.1 :001 > hash = {a: 1, b:2}
=> {:a=>1, :b=>2}
2.2.1 :002 > hash[:a]
=> 1
2.2.1 :003 > hash["a"]
=> nil
ActiveSupport::HashWithIndifferentAccess
2.2.1 :006 > hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1, b:2)
NameError: uninitialized constant ActiveSupport
from (irb):6
from /home/synerzip/.rvm/rubies/ruby-2.2.1/bin/irb:11:in `<main>'
2.2.1 :007 > require 'active_support/core_ext/hash/indifferent_access'
=> true
2.2.1 :008 > hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1, b:2)
=> {"a"=>1, "b"=>2}
2.2.1 :009 > hash[:a]
=> 1
2.2.1 :010 > hash["a"]
=> 1
class HashWithIndifferentAccess is inherited from ruby "Hash" & above special behavior is added in it.
In Ruby Hash:
hash[:key]
hash["key"]
are different. In HashWithIndifferentAccess as the name suggests, you can access key either way.
Quoting official documentation to this:
Implements a hash where keys :foo and "foo" are considered to be the
same.
and
Internally symbols are mapped to strings when used as keys in the
entire writing interface (calling []=, merge, etc). This mapping
belongs to the public interface. For example, given:
hash = ActiveSupport::HashWithIndifferentAccess.new(a: 1)
You are
guaranteed that the key is returned as a string:
hash.keys # => ["a"]

Different result for Regexp match with Rails and Rubular?

I am using Rails 4.0.0 with Ruby 2.0.0 p247. I am writing an URL regexp matcher but I have no idea why it does not work:
2.0.0-p247 :033 > REGEXP = %r{\Ahttps:\/\/#{ Rails.configuration.aws[:bucket] }\.s3(-#{Rails.configuration.aws[:region]}|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\?.+\z}.freeze
=> /\Ahttps:\/\/test-gem\.s3(-eu-west-1|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\?.+\z/
2.0.0-p247 :034 > url = "https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
=> "https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
2.0.0-p247 :035 > REGEXP.match(url)
=> nil
But when I try to debug in things like Rubular, it does work. Any idea? Thanks!
Remove \?.+ in the end if your regexp
Might be a bug with Ruby 2.0.0. I'm using 2.1.3 and it works like you'd expect.
> r = /\Ahttps:\/\/test-gem\.s3(\A-eu-west-1\z|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\z/
=> /\Ahttps:\/\/test-gem\.s3(\A-eu-west-1\z|)\.amazonaws\.com\/(?<path>uploads\/.+\/(?<filename>.+))\z/
> r.match("https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg")
=> #<MatchData
"https://test-gem.s3.amazonaws.com/uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
path:"uploads/2alrg16mvx6r-29590d114fb3257846c1a03330418da9/3031674-poster-p-1-for-25.jpg"
filename:"3031674-poster-p-1-for-25.jpg">

Rails n elements before last

In Rails I often do this:
Model.last(5).first
This retrieves element last-5.
Is there a built-in way of doing this?
The more common way is offset()
Model.offset(5).last
Edit (for lazy people):
1.8.7 :001 > User.first.id
=> 1
1.8.7 :002 > User.last.id
=> 143455
1.8.7 :003 > User.offset(5).last.id
=> 143450

ActiveRecord object marked as dirty when old value and new value are both numeric zero

I have a model called Day that represents a day in a timesheet. I've noticed that whenever I call #day.save it's writing to the database, even though none of the object's properties have had their values changed.
#day = Day.last
=> #<Day lunch_minutes: 0, updated_at: "2012-08-19 12:09:40", work_hours: 5.5>
A day has its length in hours, and the length of its lunch break in minutes, stored. I've cropped out some properties that aren't relevant.
#day.lunch_minutes
=> 0
#day.lunch_minutes = 0
=> 0
#day.changes
=> {"lunch_minutes"=>[0, 0]}
#day.lunch_minutes_changed?
=> true
That should be false. Compare to a value that isn't zero:
#day.work_hours = 5.5
=> 5.5
#day.work_hours_changed?
=> false
So if I call save, this gets called. Ideally there would be no unnecessary database interaction here.
#day.save
(0.5ms) UPDATE "days" SET "lunch_minutes" = 0, "updated_at" = '2012-08-19 12:22:59.586860' WHERE "days"."id" = 48
I'm not sure if this is a Rails bug or if I'm doing some incorrectly somewhere. It looks like it could be an issue in "changes_from_zero_to_string?" - I think adding a && value != 0 to that method would fix it - but I want to know if anyone else has seen this/a fix for this before?
What version of rails are you using? I just had a go in my app (3.1.5/1.8.7) and it doesn't behave this way.. I just used a random integer property on one of my models to test with:
1.8.7 :006 > o = Order.first
=> <Order id:...>
1.8.7 :007 > o.order_items_count
=> 0
1.8.7 :008 > o.order_items_count = 0
=> 0
1.8.7 :009 > o.changes
=> {}
1.8.7 :010 > o.order_items_count = '0'
=> "0"
1.8.7 :011 > o.changes
=> {}
1.8.7 :012 > o.save
(0.1ms) BEGIN
(0.1ms) COMMIT
=> true
It appears to be a bug.
Interestingly, according to the code, if you do:
#day.lunch_minutes = '0'
It will probably think it has not changed!
Try that, and if indeed this change causes #day.lunch_minutes_changed? to be false, then make sure it is reported as an issue to https://github.com/rails/rails.

Rails to_json Why are timestamps breaking, and being set to 2000-01-01T01:31:35Z

I'm building a json object in rails as follows:
#list = Array.new
#list << {
:created_at => item.created_at
}
end
#list.to_json
Problem is this gets received by the browser like so:
"created_at\":\"2000-01-01T01:31:35Z\"
Which is clearly not right, in the DB it has:
2011-06-17 01:31:35.057551
Why is this happening? Any way to make sure this gets to the browser correctly?
Thanks
You need to do some testing / debugging to see how that date is coming through.
For me, in Rails console (Rails 3.0.9, Ruby 1.9.2)
ruby-1.9.2-p180 :014 > d = Date.parse("2011-06-17 01:31:35.057551")
=> Fri, 17 Jun 2011
ruby-1.9.2-p180 :015 > #list = {:created_at => d}
=> {:created_at=>Fri, 17 Jun 2011}
ruby-1.9.2-p180 :016 > #list.to_json
=> "{\"created_at\":\"2011-06-17\"}"
i.e. it's just fine. Can you see whether the date is really ok?
The trouble lies with the way to_json escapes characters. There is a very good post on the subject here:
Rails to_json or as_json
You may need to look into overriding as_json.

Resources