Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

support rails 3.0

fix parser for rails 3.0
  • Loading branch information...
commit ee865c32f9657533c2c54894d08892e6d20a92f1 1 parent 8180c11
@grosser grosser authored
View
7 .travis.yml
@@ -5,6 +5,7 @@ rvm:
- ree
- rbx
gemfile:
- - gemfiles/activerecord-2.3.gemfile
- - gemfiles/activerecord-3.1.gemfile
- - gemfiles/activerecord-3.2.gemfile
+ - gemfiles/activerecord_2.3.gemfile
+ - gemfiles/activerecord_3.0.gemfile
+ - gemfiles/activerecord_3.1.gemfile
+ - gemfiles/activerecord_3.2.gemfile
View
4 Appraisals
@@ -2,6 +2,10 @@ appraise "activerecord-2.3" do
gem 'activerecord', '~> 2.3.6', :require => "active_record"
end
+appraise "activerecord-3.0" do
+ gem 'activerecord', '~> 3.0.0', :require => "active_record"
+end
+
appraise "activerecord-3.1" do
gem 'activerecord', '~> 3.1.1', :require => "active_record"
end
View
11 gemfiles/activerecord_3.0.gemfile
@@ -0,0 +1,11 @@
+# This file was generated by Appraisal
+
+source "http://rubygems.org"
+
+gem "mysql", "2.8.1", :platforms=>:ruby
+gem "activerecord-jdbcmysql-adapter", "~> 1.2.2", :platforms=>:jruby
+gem "ruby-debug", :platforms=>:mri_18
+gem "ruby-debug19", :platforms=>:mri_19
+gem "activerecord", "~> 3.0.0", :require=>"active_record"
+
+gemspec :path=>"../"
View
77 gemfiles/activerecord_3.0.gemfile.lock
@@ -0,0 +1,77 @@
+PATH
+ remote: /Users/mgrosser/code/tools/kasket
+ specs:
+ kasket (2.0.0)
+ activerecord (>= 2.3.6, < 3.3)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ activemodel (3.0.17)
+ activesupport (= 3.0.17)
+ builder (~> 2.1.2)
+ i18n (~> 0.5.0)
+ activerecord (3.0.17)
+ activemodel (= 3.0.17)
+ activesupport (= 3.0.17)
+ arel (~> 2.0.10)
+ tzinfo (~> 0.3.23)
+ activesupport (3.0.17)
+ appraisal (0.5.1)
+ bundler
+ rake
+ archive-tar-minitar (0.5.2)
+ arel (2.0.10)
+ builder (2.1.2)
+ columnize (0.3.6)
+ i18n (0.5.0)
+ linecache (0.46)
+ rbx-require-relative (> 0.0.4)
+ linecache19 (0.5.12)
+ ruby_core_source (>= 0.1.4)
+ metaclass (0.0.1)
+ mocha (0.10.5)
+ metaclass (~> 0.0.1)
+ mysql (2.8.1)
+ rake (10.0.2)
+ rbx-require-relative (0.0.9)
+ ruby-debug (0.10.4)
+ columnize (>= 0.1)
+ ruby-debug-base (~> 0.10.4.0)
+ ruby-debug-base (0.10.4)
+ linecache (>= 0.3)
+ ruby-debug-base19 (0.11.25)
+ columnize (>= 0.3.1)
+ linecache19 (>= 0.5.11)
+ ruby_core_source (>= 0.1.4)
+ ruby-debug19 (0.11.6)
+ columnize (>= 0.3.1)
+ linecache19 (>= 0.5.11)
+ ruby-debug-base19 (>= 0.11.19)
+ ruby_core_source (0.1.5)
+ archive-tar-minitar (>= 0.5.2)
+ shoulda (3.3.2)
+ shoulda-context (~> 1.0.1)
+ shoulda-matchers (~> 1.4.1)
+ shoulda-context (1.0.1)
+ shoulda-matchers (1.4.1)
+ activesupport (>= 3.0.0)
+ test-unit (2.5.2)
+ tzinfo (0.3.35)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ activerecord (~> 3.0.0)
+ activerecord-jdbcmysql-adapter (~> 1.2.2)
+ appraisal (~> 0.5)
+ bundler
+ kasket!
+ mocha (~> 0.10.5)
+ mysql (= 2.8.1)
+ rake
+ ruby-debug
+ ruby-debug19
+ shoulda
+ test-unit (~> 2.5.1)
View
4 lib/kasket.rb
@@ -16,6 +16,8 @@ module Kasket
autoload :SelectManagerMixin, 'kasket/select_manager_mixin'
autoload :RelationMixin, 'kasket/relation_mixin'
+ AR30 = (ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0)
+
CONFIGURATION = {:max_collection_size => 100}
module_function
@@ -33,7 +35,7 @@ def setup(options = {})
end
ActiveRecord::Associations::BelongsToAssociation.send(:include, Kasket::ReloadAssociationMixin)
- if ActiveRecord::VERSION::MAJOR == 2
+ if ActiveRecord::VERSION::MAJOR == 2 || AR30
ActiveRecord::Associations::BelongsToPolymorphicAssociation.send(:include, Kasket::ReloadAssociationMixin)
end
ActiveRecord::Associations::HasOneThroughAssociation.send(:include, Kasket::ReloadAssociationMixin)
View
17 lib/kasket/query_parser.rb
@@ -11,15 +11,26 @@ class QueryParser
def initialize(model_class)
@model_class = model_class
- @supported_query_pattern = /^select \* from (?:`|")#{@model_class.table_name}(?:`|") where \((.*)\)(|\s+limit 1)\s*$/i
+ @supported_query_pattern = if AR30
+ /^select\s+(?:`#{@model_class.table_name}`.)?\* from (?:`|")#{@model_class.table_name}(?:`|") where (.*?)\s*$/i
+ else
+ /^select \* from (?:`|")#{@model_class.table_name}(?:`|") where \((.*)\)(|\s+limit 1)\s*$/i
+ end
@table_and_column_pattern = /(?:(?:`|")?#{@model_class.table_name}(?:`|")?\.)?(?:`|")?([a-zA-Z]\w*)(?:`|")?/ # Matches: `users`.id, `users`.`id`, users.id, id
@key_eq_value_pattern = /^[\(\s]*#{@table_and_column_pattern}\s+(=|IN)\s+#{VALUE}[\)\s]*$/ # Matches: KEY = VALUE, (KEY = VALUE), ()(KEY = VALUE))
end
def parse(sql)
if match = @supported_query_pattern.match(sql)
+ where, limit = match[1], match[2]
+ if AR30 && where =~ /limit \d+\s*$/i
+ # limit is harder to find in rails 3.0 since where does not use surrounding braces
+ return unless where =~ /(.*?)(\s+limit 1)\s*$/i
+ where, limit = $1, $2
+ end
+
query = Hash.new
- query[:attributes] = sorted_attribute_value_pairs(match[1])
+ query[:attributes] = sorted_attribute_value_pairs(where)
return nil if query[:attributes].nil?
if query[:attributes].size > 1 && query[:attributes].map(&:last).any? {|a| a.is_a?(Array)}
@@ -28,7 +39,7 @@ def parse(sql)
end
query[:index] = query[:attributes].map(&:first)
- query[:limit] = match[2].blank? ? nil : 1
+ query[:limit] = limit.blank? ? nil : 1
query[:key] = @model_class.kasket_key_for(query[:attributes])
query[:key] << '/first' if query[:limit] == 1 && !query[:index].include?(:id)
query
View
6 lib/kasket/visitor.rb
@@ -25,7 +25,7 @@ def column_for(name)
end
def visit_Arel_Nodes_SelectStatement(node)
- return :unsupported if node.with
+ return :unsupported if !AR30 && node.with
return :unsupported if node.offset
return :unsupported if node.lock
return :unsupported if node.orders.any?
@@ -45,8 +45,8 @@ def visit_Arel_Nodes_SelectStatement(node)
def visit_Arel_Nodes_SelectCore(node)
return :unsupported if node.groups.any?
return :unsupported if node.having
- return :unsupported if node.set_quantifier
- return :unsupported if !node.source || node.source.empty?
+ return :unsupported if !AR30 && node.set_quantifier
+ return :unsupported if !AR30 && (!node.source || node.source.empty?)
return :unsupported if node.projections.size != 1
select = node.projections[0]
View
2  test/parser_test.rb
@@ -13,6 +13,8 @@ def parse(options)
end
end
scope.to_kasket_query
+ elsif ActiveRecord::VERSION::MAJOR == 3 && ActiveRecord::VERSION::MINOR == 0
+ @parser.parse(scope.scoped(options).to_sql)
else
sql = scope.send(:construct_finder_sql, options)
@parser.parse(sql)
View
10 test/reload_test.rb
@@ -1,11 +1,6 @@
require File.expand_path("helper", File.dirname(__FILE__))
class ReloadTest < ActiveSupport::TestCase
- should "load a belongs to association" do
- Kasket.expects(:clear_local)
- Comment.first.post
- end
-
context "Loading a polymorphic belongs_to" do
should "not clear cache when loading nil" do
@post = Post.first
@@ -42,11 +37,6 @@ class ReloadTest < ActiveSupport::TestCase
assert @post.poly
end
- should "clear local when it is unloaded" do
- Kasket.expects(:clear_local)
- assert Post.first.poly
- end
-
should "clear local when it is loaded" do
Kasket.expects(:clear_local)
@post.poly.reload
Please sign in to comment.
Something went wrong with that request. Please try again.