activerecord-hackery/ransack — pull request #309 by seanlinsley (2013-11-27 06:10:42+00:00)
Title: Improve predicate detection performance from .7 ms to .1 ms

Depending on the page, Ransack's `detect_from_string` and `detect_and_strip_from_string!` could be called many times. For example, on one page `detect_and_strip_from_string!` is being called 121 times, making the page take 40 ms longer to load:
![screen shot 2013-11-26 at 11 38 43 pm](https://f.cloud.github.com/assets/688886/1629105/8dde862a-5729-11e3-87e3-2db8cbcc8d0d.png)

I took a stab at a couple different fixes; here's an illustration:
```ruby
class Ransack::Predicate
def self.detect_via_joined_regex(str)
str =~ /_(#{names_by_decreasing_length.join '|' })$/
end

def self.detect_via_end_with(str)
names_by_decreasing_length.detect{ |p| str.end_with? '_' + p }
end
end

def time
start = Time.now
yield
(Time.now - start) * 1000 # ms
end

time{ Ransack::Predicate.detect_and_strip_from_string! 'foo_bar' }
# => 0.731
time{ Ransack::Predicate.detect_from_string 'foo_bar' }
# => 0.752
time{ Ransack::Predicate.detect_via_joined_regex 'foo_bar' }
# => 0.458
time{ Ransack::Predicate.detect_via_end_with 'foo_bar' }
# => 0.106
```

As you can see, `String#end_with?` is significantly faster than building and testing 50+ regular expressions each time the method is called.

Some added benchmarks:
```ruby
subject = Ransack::Predicate
n = 10_000

Benchmark.bmbm do |x|
x.report 'detect and strip' do n.times do subject.detect_and_strip_from_string! 'foo_bar' end end
x.report 'detect' do n.times do subject.detect_from_string 'foo_bar' end end
x.report 'joined regex' do n.times do subject.detect_via_joined_regex 'foo_bar' end end
x.report 'String#end_with?' do n.times do subject.detect_via_end_with 'foo_bar' end end
end
```
```
Rehearsal ----------------------------------------------------
detect and strip 7.080000 0.170000 7.250000 ( 7.251518)
detect 7.170000 0.170000 7.340000 ( 7.344822)
joined regex 3.270000 0.020000 3.290000 ( 3.282885)
String#end_with? 0.920000 0.000000 0.920000 ( 0.920259)
------------------------------------------ total: 18.800000sec

user system total real
detect and strip 7.080000 0.180000 7.260000 ( 7.263497)
detect 7.180000 0.160000 7.340000 ( 7.329569)
joined regex 3.220000 0.010000 3.230000 ( 3.221820)
String#end_with? 0.920000 0.000000 0.920000 ( 0.920419)