1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

formatting insert and update statements

- values need to be coerced to the type corresponding to the column
This commit is contained in:
Nick Kallen 2008-03-16 16:14:02 -07:00
parent ed9c8d4d82
commit af3d7c5193
8 changed files with 110 additions and 45 deletions

1
TODO
View file

@ -1,5 +1,4 @@
todo:
- remove to_sql logic from array and hash, push it into a formatter
- string passthrough:
:joins=>"INNER JOIN posts ON comments.post_id = posts.id"
:conditions=>"(`posts`.author_id = 1)",

View file

@ -3,7 +3,7 @@ class Array
Hash[*flatten]
end
def to_sql(formatter = Sql::SelectExpression.new)
formatter.array self
def to_sql(formatter = nil)
"(" + collect { |e| e.to_sql(formatter) }.join(', ') + ")"
end
end

View file

@ -8,12 +8,4 @@ class Hash
descendent.merge(yield(key) => yield(value))
end
end
def to_sql(formatter = nil)
'(' +
inject([]) do |values, (key, value)|
values << key.format(value)
end.join(', ') +
')'
end
end

View file

@ -11,7 +11,7 @@ module ActiveRelation
"INSERT",
"INTO #{table_sql}",
"(#{record.keys.collect(&:to_sql)})",
"VALUES #{record.to_sql}"
"VALUES (#{record.collect { |key, value| key.format(value) }})"
].join("\n")
end

View file

@ -9,9 +9,9 @@ module ActiveRelation
def to_sql(formatter = nil)
[
"UPDATE #{table_sql} SET",
assignments.inject("") do |assignments, (attribute, value)|
assignments << " #{attribute.to_sql} = #{value.to_sql}"
end,
assignments.collect do |attribute, value|
"#{value.format(attribute)} = #{attribute.format(value)}"
end.join("\n"),
("WHERE #{selects.collect(&:to_sql).join('\n\tAND ')}" unless selects.blank?)
].join("\n")
end

View file

@ -54,19 +54,25 @@ module ActiveRelation
end
describe 'when relating to an array' do
describe 'when given an arry of elements of the same type of the attribute' do
it 'manufactures sql with a list' do
array = [1, 2, 3]
ConcreteBinary.new(@attribute1, array.bind(@relation)).to_sql.should be_like("
describe 'when the array\'s elements are the same type as the attribute' do
before do
@array = [1, 2, 3]
end
it 'manufactures sql with a comma separated list' do
ConcreteBinary.new(@attribute1, @array.bind(@relation)).to_sql.should be_like("
`users`.`id` <=> (1, 2, 3)
")
end
end
describe 'when given an array, the elements of which are not the same type as the attribute' do
it 'formats values in the array in the type of the attribute' do
array = ['1-asdf', 2, 3]
ConcreteBinary.new(@attribute1, array.bind(@relation)).to_sql.should be_like("
describe 'when the array\'s elements are not same type as the attribute' do
before do
@array = ['1-asdf', 2, 3]
end
it 'formats values in the array as the type of the attribute' do
ConcreteBinary.new(@attribute1, @array.bind(@relation)).to_sql.should be_like("
`users`.`id` <=> (1, 2, 3)
")
end

View file

@ -4,20 +4,57 @@ module ActiveRelation
describe Insertion do
before do
@relation = Table.new(:users)
@insertion = Insertion.new(@relation, @relation[:name] => "nick".bind(@relation))
end
describe '#to_sql' do
it 'manufactures sql inserting the data for one item' do
@insertion.to_sql.should be_like("
INSERT
INTO `users`
(`users`.`name`) VALUES ('nick')
")
describe 'when given values whose types correspond to the types of the attributes' do
before do
@insertion = Insertion.new(@relation, @relation[:name] => "nick".bind(@relation))
end
it 'manufactures sql inserting data' do
@insertion.to_sql.should be_like("
INSERT
INTO `users`
(`users`.`name`) VALUES ('nick')
")
end
end
describe 'when given values whose types differ from from the types of the attributes' do
before do
@insertion = Insertion.new(@relation, @relation[:id] => '1-asdf'.bind(@relation))
end
it 'manufactures sql inserting data' do
@insertion.to_sql.should be_like("
INSERT
INTO `users`
(`users`.`id`) VALUES (1)
")
end
end
describe 'when given values whose types correspond to the type of the attribtues' do
before do
@insertion = Insertion.new(@relation, @relation[:name] => "nick".bind(@relation))
end
it 'manufactures sql inserting data' do
@insertion.to_sql.should be_like("
INSERT
INTO `users`
(`users`.`name`) VALUES ('nick')
")
end
end
end
describe '#call' do
before do
@insertion = Insertion.new(@relation, @relation[:name] => "nick".bind(@relation))
end
it 'executes an insert on the connection' do
mock(connection = Object.new).insert(@insertion.to_sql)
@insertion.call(connection)

View file

@ -7,27 +7,58 @@ module ActiveRelation
end
describe '#to_sql' do
it 'manufactures sql updating attributes' do
Update.new(@relation, @relation[:name] => "nick".bind(@relation)).to_sql.should be_like("
UPDATE `users`
SET `users`.`name` = 'nick'
")
describe 'when given values whose types correspond to the types of the attributes' do
before do
@update = Update.new(@relation, @relation[:name] => "nick".bind(@relation))
end
it 'manufactures sql updating attributes' do
@update.to_sql.should be_like("
UPDATE `users`
SET `users`.`name` = 'nick'
")
end
end
it 'manufactures sql updating a selection relation' do
Update.new(@relation.select(@relation[:id].equals(1)), @relation[:name] => "nick".bind(@relation)).to_sql.should be_like("
UPDATE `users`
SET `users`.`name` = 'nick'
WHERE `users`.`id` = 1
")
describe 'when given values whose types differ from from the types of the attributes' do
before do
@update = Update.new(@relation, @relation[:id] => '1-asdf'.bind(@relation))
end
it 'manufactures sql updating attributes' do
@update.to_sql.should be_like("
UPDATE `users`
SET `users`.`id` = 1
")
end
end
describe 'when the relation is a selection' do
before do
@update = Update.new(
@relation.select(@relation[:id].equals(1)),
@relation[:name] => "nick".bind(@relation)
)
end
it 'manufactures sql updating a selection relation' do
@update.to_sql.should be_like("
UPDATE `users`
SET `users`.`name` = 'nick'
WHERE `users`.`id` = 1
")
end
end
end
describe '#call' do
before do
@update = Update.new(@relation, @relation[:name] => "nick".bind(@relation))
end
it 'executes an update on the connection' do
update = Update.new(@relation, @relation[:name] => "nick".bind(@relation))
mock(connection = Object.new).update(update.to_sql)
update.call(connection)
mock(connection = Object.new).update(@update.to_sql)
@update.call(connection)
end
end