aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
Commit message (Collapse)AuthorAgeFilesLines
* Merge pull request #20848 from ↵Arthur Nogueira Neves2015-09-141-1/+1
|\ | | | | | | | | deivid-rodriguez/fix_undefined_method_error_on_exception Fix undefined method error on exception
| * Fix undefined method error on exceptionDavid Rodríguez2015-07-111-1/+1
| | | | | | | | | | | | The `error` method is not defined, in general, for exceptions. Instead, print the exception message. This error was hiding actual meaningful DB configuration errors. See http://stackoverflow.com/questions/18774463.
* | Fix doc of limit option for a text column [ci skip]Ryuta Kamizono2015-09-141-2/+2
| | | | | | | | | | | | | | | | | | Follow up #21591. The document of limit option for a text column is incorrect. MySQL: the limit is byte length, not character length Pg, Sqlite3: variable unlimited length
* | Merge pull request #21591 from kamipo/text_and_blob_limit_is_byte_lengthRafael Mendonça França2015-09-131-2/+2
|\ \ | | | | | | TEXT and BLOB limit is byte length, not character length.
| * | TEXT and BLOB limit is byte length, not character length.Ryuta Kamizono2015-09-111-2/+2
| | |
* | | Merge pull request #21568 from amitsuroliya/mysql_version_updateRafael Mendonça França2015-09-135-9/+9
|\ \ \ | |/ / |/| | Updated MySQL documentation link to MySQL latest version 5.7 everywhe…
| * | Updated MySQL documentation link to MySQL latest version 5.7 everywhere [ci ↵amitkumarsuroliya2015-09-105-9/+9
| | | | | | | | | | | | | | | skip] Bumps from `5.6` to `5.7`
* | | Explicitly require AR/attribute where using itAkira Matsuda2015-09-101-0/+2
|/ / | | | | | | | | autoloading this could possibly cause some weird race condition when calling an AR::Attribute's singleton method on a threaded server.
* | remove dead code.Yves Senn2015-09-092-7/+1
| | | | | | | | | | | | The last call site of `last_version` was removed with: 838e18321118ee3ec6669217e5ea0216f79c969a
* | Merge pull request #21486 from bogdan/refactor-has-many-counter-cacheEileen M. Uchitelle2015-09-094-71/+61
|\ \ | | | | | | HasManyAssociation: moved half of counter cache code to reflection
| * | HasManyAssociation: moved half of counter cache code to reflectionBogdan Gusiev2015-09-034-71/+61
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Current implementation has a lot of utility methods that accept reflection call a lot of methods on it and exit. E.g. has_counter_cache?(reflection) It causes confusion and inability to cache result of the method even through it always returns the same result for the same reflection object. It can be done easier without access to the association context by moving code into reflection itself. e.g. reflection.has_counter_cache? Reflection is less complex object than association so moving code there automatically makes it simplier to understand.
* | | Merge pull request #21529 from rngtng/move-migrations-paths-to-database-taskYves Senn2015-09-091-7/+7
|\ \ \ | | | | | | | | | | | | Use `ActiveRecord::Tasks::DatabaseTasks.migrations_paths` explicit for db tasks
| * | | Use `ActiveRecord::Tasks::DatabaseTasks.migrations_paths` instead of ↵Tobias Bielohlawek2015-09-071-9/+8
| | | | | | | | | | | | | | | | `Migrator.migrations_paths`
* | | | remove dead code.Yves Senn2015-09-091-4/+0
| | | | | | | | | | | | | | | | This method is private API and never used. Let's remove it.
* | | | adjust method visibility according to it's usage.Yves Senn2015-09-091-18/+18
| | | | | | | | | | | | | | | | | | | | `Schema#migrations_paths` is not supposed to be public API. In fact it's only used inside `Schema` itself, so let's make it private.
* | | | Don't set the default argumentRafael Mendonça França2015-09-091-1/+1
| | | | | | | | | | | | | | | | It is always passed in
* | | | Invert the conditionalRafael Mendonça França2015-09-091-1/+1
| | | |
* | | | Remove dead codeRafael Mendonça França2015-09-091-6/+0
| | | | | | | | | | | | | | | | Usage was removed in 5c4495538b
* | | | Revert "Merge pull request #20080 from ↵Rafael Mendonça França2015-09-093-24/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | robertjlooby/fix_overwriting_by_dynamic_finders" This reverts commit d5ba9a42a6e93b163a49f99d739aa56820e044d0, reversing changes made to 30c503395bf6bf7db1ec0295bd661ce644628db5. Reason: This generate the dynalic finders more than one time
* | | | Merge pull request #20080 from robertjlooby/fix_overwriting_by_dynamic_findersRafael Mendonça França2015-09-093-3/+24
|\ \ \ \ | | | | | | | | | | | | | | | put dynamic matchers on GeneratedAssociationMethods instead of model
| * | | | put dynamic matchers on the GeneratedAssociationMethods instead of modelRob Looby2015-05-083-3/+24
| | | | |
* | | | | Merge pull request #21554 from ronakjangir47/added_nodocRafael Mendonça França2015-09-091-1/+1
|\ \ \ \ \ | | | | | | | | | | | | Added nodoc tag for the methods which returns object of private apis
| * | | | | Added nodoc for `arel` method which returns object of private api. [ci skip]Ronak Jangir2015-09-091-1/+1
| | | | | |
* | | | | | Merge pull request #20921 from pboling/fix-sql-colors-in-log-subscriberRafael Mendonça França2015-09-092-7/+125
|\ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | | Fix and Improve sql logging coloration in `ActiveRecord::LogSubscriber`.
| * | | | | | Remove extraneous `then` from case statementPeter Boling2015-07-172-14/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - CR feedback from @egilburg Additionally - Move logic for colorizing the payload name into a separate method - Make some `ActiveRecord::LogSubscriber` instance methods private for clarity: - `colorize_payload_name` - `sql_color` - `logger` - Improve Changelog Documentation GH #20885
| * | | | | | Improve sql logging coloration in `ActiveRecord::LogSubscriber`.Peter Boling2015-07-173-7/+143
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | - Improves coloring for statements like: # Become WHITE SELECT * FROM ( SELECT * FROM mytable FOR UPDATE ) ss WHERE col1 = 5; LOCK TABLE table_name IN ACCESS EXCLUSIVE MODE; # Becomes RED ROLLBACK - Reinstates the coloration of the `payload[:name]`. Instead of simple alternating colors, adds meaning: - `MAGENTA` for `"SQL"` or `blank?` payload names - `CYAN` for Model Load/Exists - Introduces specs for sql coloration. - Introduces specs for payload name coloration. GH#20885
* | | | | | | Fix docs of AR::Timestamp to match #15726claudiob2015-09-081-5/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | [ci skip] @sgrif can you review when you have time? Thanks!
* | | | | | | Merge pull request #21535 from dmitry/feature/validate-multiple-contextsRafael Mendonça França2015-09-082-1/+12
|\ \ \ \ \ \ \ | |_|/ / / / / |/| | | | | | Validate multiple contexts on `valid?` and `invalid?` at once
| * | | | | | Validate multiple contexts on `valid?` and `invalid?` at once.Dmitry Polushkin2015-09-072-1/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Example: ```ruby class Person include ActiveModel::Validations attr_reader :name, :title validates_presence_of :name, on: :create validates_presence_of :title, on: :update end person = Person.new person.valid?([:create, :update]) # => true person.errors.messages # => {:name=>["can't be blank"], :title=>["can't be blank"]} ```
* | | | | | | Merge pull request #21511 from rwz/ar-exceptions-no-argsEileen M. Uchitelle2015-09-085-66/+178
|\ \ \ \ \ \ \ | | | | | | | | | | | | | | | | Removes mandatory arguments from AR exceptions
| * | | | | | | Make ActiveRecordException descendants args optionalPavel Pravosud2015-09-075-66/+178
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This change allows to instantiate all ActiveRecordError descendant execption classes without arguments, which might be useful in testing and is far less surprising than mandatory arguments.
* | | | | | | | Merge pull request #21548 from yui-knk/feature/define_tables_as_interfaceYves Senn2015-09-081-0/+5
|\ \ \ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | Define `SchemaStatements#tables` as interface
| * | | | | | | | Define `SchemaStatements#tables` as interfaceyui-knk2015-09-081-0/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | These 3 methods expect `ConnectionAdapters` to have `tables` method, so make it clear that `tables` method is interface. * `ConnectionAdapters::SchemaCache#prepare_tables` * `db:schema:cache:dump` task * `SchemaDumper#tables`
* | | | | | | | | Merge pull request #21530 from arvindmehra/am-ar-to-activerecordYves Senn2015-09-082-2/+2
|\ \ \ \ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | Replace AR with ActiveRecord to make it more readable [ci skip]
| * | | | | | | | | Replace AR with ActiveRecord to make it more readable [ci skip]arvind2015-09-082-2/+2
| |/ / / / / / / /
* | | | | | | | | Merge pull request #21528 from yui-knk/test/add_tests_for_mysql2_viewYves Senn2015-09-082-64/+66
|\ \ \ \ \ \ \ \ \ | |/ / / / / / / / |/| | | | | | | | Add tests for test/cases/adapters/mysql2/view_test.rb
| * | | | | | | | Add view tests for MySQLyui-knk2015-09-082-64/+66
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Basically view tests for MySQL are same with `test/cases/adapters/postgresql/view_test.rb`. So move `test/cases/adapters/postgresql/view_test.rb` to `test/cases/view_test.rb` and make them only run if `current_adapter` supports writable view.
* | | | | | | | | :bomb:Rafael Mendonça França2015-09-081-1/+1
| | | | | | | | |
* | | | | | | | | Memoized reflections accessorRafael Mendonça França2015-09-081-9/+18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Its value never change since associations are defined at class load time so there is no need to build the hash everytime the method is called. Before this change: Calculating ------------------------------------- reflections 804.000 i/100ms ------------------------------------------------- reflections 8.213k (±26.2%) i/s - 36.180k After this change: Calculating ------------------------------------- reflections 24.548k i/100ms ------------------------------------------------- reflections 1.591M (±25.7%) i/s - 7.364M Benchmark script: require 'bundler/setup' require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do 100.times do |i| create_table "users#{i}", force: true end create_table :cars, force: true do |t| 100.times do |i| t.references "users#{i}" end end end class Car < ActiveRecord::Base 100.times do |i| belongs_to "users#{i}".to_sym end end Benchmark.ips do |x| x.report('reflections') { Car.reflections } end
* | | | | | | | | Merge pull request #21537 from tgxworld/perf_reduce_allocationRafael Mendonça França2015-09-071-5/+5
|\ \ \ \ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | PERF: Reduce allocation in `resolve_column_aliases`.
| * | | | | | | | | Reduce allocation in `resolve_column_aliases`.Guo Xiang Tan2015-09-081-5/+5
| | |_|/ / / / / / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Benchmark Script Used: ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' gem 'rails', path: '~/rails' # master against ref "f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06" gem 'arel', github: 'rails/arel', branch: 'master' gem 'rack', github: 'rack/rack', branch: 'master' gem 'sass' gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master' gem 'sprockets', github: 'rails/sprockets', branch: 'master' gem 'pg' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('postgres://postgres@localhost:5432/rubybench') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.timestamps null: false end end class User < ActiveRecord::Base; end attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", } 1000.times { User.create!(attributes) } Benchmark.ips(5, 3) do |x| x.report('where with hash single') { User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.report('where with string single') { User.where("users.name = ?", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.report('where with hash double') { User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com") } x.report('where with string double') { User.where("users.name = ? AND users.email = ?", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", "foobar@email.com") } x.compare! end ``` Before: ``` Calculating ------------------------------------- where with hash single 3.300k i/100ms where with string single 4.965k i/100ms where with hash double 2.594k i/100ms where with string double 4.400k i/100ms ------------------------------------------------- where with hash single 35.161k (± 1.2%) i/s - 178.200k where with string single 53.368k (± 2.9%) i/s - 268.110k where with hash double 27.364k (± 1.1%) i/s - 137.482k where with string double 46.876k (± 2.1%) i/s - 237.600k Comparison: where with string single: 53368.1 i/s where with string double: 46875.5 i/s - 1.14x slower where with hash single: 35160.8 i/s - 1.52x slower where with hash double: 27364.0 i/s - 1.95x slower ``` After: ``` Calculating ------------------------------------- where with hash single 3.403k i/100ms where with string single 5.167k i/100ms where with hash double 2.659k i/100ms where with string double 4.597k i/100ms ------------------------------------------------- where with hash single 36.410k (± 1.3%) i/s - 183.762k where with string single 55.009k (± 2.6%) i/s - 279.018k where with hash double 27.951k (± 1.4%) i/s - 140.927k where with string double 48.362k (± 2.6%) i/s - 243.641k Comparison: where with string single: 55008.6 i/s where with string double: 48361.5 i/s - 1.14x slower where with hash single: 36410.1 i/s - 1.51x slower where with hash double: 27950.9 i/s - 1.97x slower ```
* / | | | | | | | Support mysql2 0.4.0, first release with prepared statements supportJeremy Daer2015-09-071-1/+1
|/ / / / / / / / | | | | | | | | | | | | | | | | | | | | | | | | Known failure on Ruby 2.3/trunk: brianmario/mysql2#671
* | | | | | | | Use Hash[] instead of Hash#dup in resolve_column_aliasesRafael Mendonça França2015-09-071-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Related with #20418
* | | | | | | | Revert "Merge pull request #21069 from ↵Rafael Mendonça França2015-09-072-12/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dmitry/feature/validate-multiple-contexts-at-once" This reverts commit 51dd2588433457960cca592d5b5dac6e0537feac, reversing changes made to ecb4e4b21b3222b823fa24d4a0598b1f2f63ecfb. This broke Active Record tests
* | | | | | | | Merge pull request #21069 from dmitry/feature/validate-multiple-contexts-at-onceRafael Mendonça França2015-09-072-1/+12
|\ \ \ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | | | | | | | | Validate multiple contexts on `valid?` and `invalid?` at once
| * | | | | | | | Validate multiple contexts on `valid?` and `invalid?` at once.Dmitry Polushkin2015-07-302-1/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Example: ```ruby class Person include ActiveModel::Validations attr_reader :name, :title validates_presence_of :name, on: :create validates_presence_of :title, on: :update end person = Person.new person.valid?([:create, :update]) # => true person.errors.messages # => {:name=>["can't be blank"], :title=>["can't be blank"]} ```
* | | | | | | | | Merge pull request #21522 from tgxworld/scope_perfRafael Mendonça França2015-09-074-5/+13
|\ \ \ \ \ \ \ \ \ | | | | | | | | | | | | | | | | | | | | PERF: Scope performance.
| * | | | | | | | | Cache check if `default_scope` has been overridden.Guo Xiang Tan2015-09-071-1/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Benchmark Script: ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' # gem 'rails', github: 'rails/rails', ref: 'f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06' gem 'rails', path: '~/rails' gem 'arel', github: 'rails/arel', branch: 'master' gem 'rack', github: 'rack/rack', branch: 'master' gem 'sass' gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master' gem 'sprockets', github: 'rails/sprockets', branch: 'master' gem 'pg' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('postgres://postgres@localhost:5432/rubybench') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.timestamps null: false end end class User < ActiveRecord::Base; end attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", } 1000.times { User.create!(attributes) } Benchmark.ips(5, 3) do |x| x.report('where with hash') { User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.report('where with string') { User.where("users.name = ?", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.compare! end key = if RUBY_VERSION < '2.2' :total_allocated_object else :total_allocated_objects end before = GC.stat[key] User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") after = GC.stat[key] puts "Total Allocated Object: #{after - before}" ``` Stackprof output truncated. ``` TOTAL (pct) SAMPLES (pct) FRAME 52 (10.6%) 10 (2.0%) ActiveRecord::Scoping::Default::ClassMethods#build_default_scope ``` Before: ``` Calculating ------------------------------------- where with hash 2.789k i/100ms where with string 4.407k i/100ms ------------------------------------------------- where with hash 29.170k (± 1.9%) i/s - 147.817k where with string 46.954k (± 2.7%) i/s - 237.978k Comparison: where with string: 46954.3 i/s where with hash: 29169.9 i/s - 1.61x slower Total Allocated Object: 85 Calculating ------------------------------------- all 16.773k i/100ms ------------------------------------------------- all 186.102k (± 3.6%) i/s - 939.288k ``` After: ``` Calculating ------------------------------------- where with hash 3.014k i/100ms where with string 4.623k i/100ms ------------------------------------------------- where with hash 31.524k (± 1.3%) i/s - 159.742k where with string 49.948k (± 2.3%) i/s - 249.642k Comparison: where with string: 49948.3 i/s where with hash: 31524.3 i/s - 1.58x slower Total Allocated Object: 84 Calculating ------------------------------------- all 20.139k i/100ms ------------------------------------------------- all 227.860k (± 2.5%) i/s - 1.148M ```
| * | | | | | | | | Reduce calls to stringify_keys.Guo Xiang Tan2015-09-073-4/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Stackprof output truncated. ``` TOTAL (pct) SAMPLES (pct) FRAME 23 (4.7%) 12 (2.4%) Hash#transform_keys 11 (2.2%) 11 (2.2%) block in Hash#transform_keys 30 (6.1%) 7 (1.4%) Hash#stringify_keys ``` Benchmark Script: ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' gem 'rails', path: '~/rails' # master against ref "f1f0a3f8d99aef8aacfa81ceac3880dcac03ca06" gem 'arel', github: 'rails/arel', branch: 'master' gem 'rack', github: 'rack/rack', branch: 'master' gem 'sass' gem 'sprockets-rails', github: 'rails/sprockets-rails', branch: 'master' gem 'sprockets', github: 'rails/sprockets', branch: 'master' gem 'pg' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('postgres://postgres@localhost:5432/rubybench') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.timestamps null: false end end class User < ActiveRecord::Base; end attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", } 1000.times { User.create!(attributes) } Benchmark.ips(5, 3) do |x| x.report('where with hash') { User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.report('where with string') { User.where("users.name = ?", "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") } x.compare! end key = if RUBY_VERSION < '2.2' :total_allocated_object else :total_allocated_objects end before = GC.stat[key] User.where(name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.") after = GC.stat[key] puts "Total Allocated Object: #{after - before}" ``` Before: ``` Calculating ------------------------------------- where with hash 2.796k i/100ms where with string 4.338k i/100ms ------------------------------------------------- where with hash 29.177k (± 1.5%) i/s - 148.188k where with string 47.419k (± 2.8%) i/s - 238.590k Comparison: where with string: 47419.0 i/s where with hash: 29176.6 i/s - 1.63x slower Total Allocated Object: 85 ``` After: ``` Calculating ------------------------------------- where with hash 2.895k i/100ms where with string 4.416k i/100ms ------------------------------------------------- where with hash 30.758k (± 2.0%) i/s - 156.330k where with string 47.708k (± 2.6%) i/s - 238.464k Comparison: where with string: 47707.9 i/s where with hash: 30757.7 i/s - 1.55x slower Total Allocated Object: 84 ```
* | | | | | | | | | Correct query for PostgreSQL 8.2Matthew Draper2015-09-082-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Generic cast-to-text was only added in 8.3.