Skip to content

Commit

Permalink
Add Relation#create_with to explictily specify create scope
Browse files Browse the repository at this point in the history
  • Loading branch information
lifo committed Jan 3, 2010
1 parent a115b5d commit a681658
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
16 changes: 9 additions & 7 deletions activerecord/lib/active_record/relation.rb
Expand Up @@ -6,7 +6,7 @@ class Relation


attr_reader :relation, :klass attr_reader :relation, :klass
attr_writer :readonly, :table attr_writer :readonly, :table
attr_accessor :preload_associations, :eager_load_associations, :includes_associations attr_accessor :preload_associations, :eager_load_associations, :includes_associations, :create_with_attributes


def initialize(klass, relation) def initialize(klass, relation)
@klass, @relation = klass, relation @klass, @relation = klass, relation
Expand Down Expand Up @@ -124,7 +124,7 @@ def reload
end end


def reset def reset
@first = @last = @create_scope = @to_sql = @order_clause = nil @first = @last = @to_sql = @order_clause = @scope_for_create = nil
@records = [] @records = []
self self
end end
Expand Down Expand Up @@ -163,13 +163,15 @@ def method_missing(method, *args, &block)
end end


def with_create_scope def with_create_scope
@klass.send(:with_scope, :create => create_scope) { yield } @klass.send(:with_scope, :create => scope_for_create) { yield }
end end


def create_scope def scope_for_create
@create_scope ||= wheres.inject({}) do |hash, where| @scope_for_create ||= begin
hash[where.operand1.name] = where.operand2.value if where.is_a?(Arel::Predicates::Equality) @create_with_attributes || wheres.inject({}) do |hash, where|
hash hash[where.operand1.name] = where.operand2.value if where.is_a?(Arel::Predicates::Equality)
hash
end
end end
end end


Expand Down
4 changes: 4 additions & 0 deletions activerecord/lib/active_record/relation/query_methods.rb
Expand Up @@ -17,6 +17,10 @@ def readonly(status = true)
spawn.tap {|r| r.readonly = status } spawn.tap {|r| r.readonly = status }
end end


def create_with(attributes = {})
spawn.tap {|r| r.create_with_attributes = attributes }
end

def select(selects) def select(selects)
if selects.present? if selects.present?
relation = spawn(@relation.project(selects)) relation = spawn(@relation.project(selects))
Expand Down
10 changes: 10 additions & 0 deletions activerecord/lib/active_record/relation/spawn_methods.rb
Expand Up @@ -6,6 +6,7 @@ def spawn(relation = @relation)
relation.preload_associations = @preload_associations relation.preload_associations = @preload_associations
relation.eager_load_associations = @eager_load_associations relation.eager_load_associations = @eager_load_associations
relation.includes_associations = @includes_associations relation.includes_associations = @includes_associations
relation.create_with_attributes = @create_with_attributes
relation.table = table relation.table = table
relation relation
end end
Expand All @@ -32,6 +33,14 @@ def merge(r)
merged_order = relation_order.present? ? relation_order : order_clause merged_order = relation_order.present? ? relation_order : order_clause
merged_relation = merged_relation.order(merged_order) merged_relation = merged_relation.order(merged_order)


merged_relation.create_with_attributes = @create_with_attributes

if @create_with_attributes && r.create_with_attributes
merged_relation.create_with_attributes = @create_with_attributes.merge(r.create_with_attributes)
else
merged_relation.create_with_attributes = r.create_with_attributes || @create_with_attributes
end

merged_wheres = @relation.wheres merged_wheres = @relation.wheres


r.wheres.each do |w| r.wheres.each do |w|
Expand All @@ -56,6 +65,7 @@ def except(*skips)
end end


result.readonly = self.readonly unless skips.include?(:readonly) result.readonly = self.readonly unless skips.include?(:readonly)
result.create_with_attributes = @create_with_attributes unless skips.include?(:create_with)


result = result.joins(@relation.joins(@relation)) unless skips.include?(:joins) result = result.joins(@relation.joins(@relation)) unless skips.include?(:joins)
result = result.group(@relation.groupings) unless skips.include?(:group) result = result.group(@relation.groupings) unless skips.include?(:group)
Expand Down
8 changes: 8 additions & 0 deletions activerecord/test/cases/relations_test.rb
Expand Up @@ -545,6 +545,14 @@ def test_create_bang
assert_equal 'hen', hen.name assert_equal 'hen', hen.name
end end


def test_explicit_create_scope
hens = Bird.where(:name => 'hen')
assert_equal 'hen', hens.new.name

hens = hens.create_with(:name => 'cock')
assert_equal 'cock', hens.new.name
end

def test_except def test_except
relation = Post.where(:author_id => 1).order('id ASC').limit(1) relation = Post.where(:author_id => 1).order('id ASC').limit(1)
assert_equal [posts(:welcome)], relation.all assert_equal [posts(:welcome)], relation.all
Expand Down

0 comments on commit a681658

Please sign in to comment.