diff options
-rw-r--r-- | CONVENTIONS | 17 | ||||
-rw-r--r-- | TODO | 18 | ||||
-rw-r--r-- | lib/active_relation/relations/relation.rb | 4 | ||||
-rw-r--r-- | lib/active_relation/sql.rb | 6 | ||||
-rw-r--r-- | spec/active_relation/unit/relations/projection_spec.rb | 38 |
5 files changed, 61 insertions, 22 deletions
diff --git a/CONVENTIONS b/CONVENTIONS new file mode 100644 index 0000000000..0d7c1b4ef0 --- /dev/null +++ b/CONVENTIONS @@ -0,0 +1,17 @@ +This file should ultimately be replaced by a series of tests, something like a lint tool. + +- all describes and its should use single quotes unless they have nested quotes. +- object instantiation in tests for all objects that are not the SUT should be manufactured in a before +- 'should' and other counterfactuals/subjunctive forms should not be used in tests +- no doubles should be used except for behaviorist testing + - behaviorist testing is desirable only when interacting with the database or the session +- when unit testing, always demonstrate behavior by using a real world example (as in, a public use of the API), so as to provide documentation. +- use collect rather than map +- jargon: + - 'obtains' is preferred to 'returns true' + - 'manufactures' +- in tests + - when manufacturing expected values (right-hand-side of should), avoid convenience methods -- construct it by initializing the object directly (Foo.new(...)). This ensures equality expectations in tests is rigorous. + - the SUT should be manufactured inline inside the test, not in a before + - dependencies for the SUT should be manufactured using convenience methods (or whatever is most terse). +- group conceptually related methods in a class within an inline module; immediately include that module.
\ No newline at end of file @@ -1,34 +1,26 @@ todo: - string passthrough: :joins=>"INNER JOIN posts ON comments.post_id = posts.id" - :conditions=>"(`posts`.author_id = 1)", :select=>"`comments`.*" - :conditions=>"1 = 1" - need adapters for this form: {:conditions=>["approved = ?", false]} {:conditions=>{:approved=>false}} {:conditions=>{"topics.approved"=>false}} {:conditions=>{:address=>#<Address:0x3489b3c @street="Funny Street", @country="Loony Land", @city="Scary Town">, "customers.name"=>"David1"}} - -- orders need string pass through - :order=>"developers.name desc, developers.id desc", -- orders need to be composable +- re-evaluate bind -- does bind belong inside the relation / predicate classes or in the factory methods? - #bind in Attribute and Expression should be doing a descend? - try to make aggration testing in join spec to be a bit more unit-like - finish pending tests - test relation, table reset - cache expiry on write - rewrite of querycache test in light of this -- relation inclusion when given an array (1,2,3,4) should quote the elements using the appropriate quoting formatter taken from the attribute - - descend on array, along with bind written in terms of it - standardize quoting - use strings everywhere, not symbols ? - "unit" test sql strategies - use real world examples, so they should be like a tutorial. - rename the tion (Selection) classes so that words that don't end in tion don't seem inconsistent -- re-evaluate bind - mock out database done: @@ -67,4 +59,10 @@ done: - renamed to #format: operand1.format(operand2) - rename sql strategies - need to_sql for ranges - - {:conditions=>{:id=>2..3}}
\ No newline at end of file + - {:conditions=>{:id=>2..3}} +- nested orderings +- string passthrough + - conditions + - orderings +- relation inclusion when given an array (1,2,3,4) should quote the elements using the appropriate quoting formatter taken from the attribute + - descend on array, along with bind written in terms of it diff --git a/lib/active_relation/relations/relation.rb b/lib/active_relation/relations/relation.rb index fa66bd039b..88d1bce4a8 100644 --- a/lib/active_relation/relations/relation.rb +++ b/lib/active_relation/relations/relation.rb @@ -42,7 +42,7 @@ module ActiveRelation end def project(*attributes) - Projection.new(self, *attributes.collect {|a| a.bind(self)}) + Projection.new(self, *attributes) end def as(aliaz) @@ -103,7 +103,7 @@ module ActiveRelation def to_sql(formatter = Sql::SelectStatement.new(engine)) formatter.select [ - "SELECT #{attributes.collect { |a| a.to_sql(Sql::SelectExpression.new(engine)) }.join(', ')}", + "SELECT #{attributes.collect { |a| a.to_sql(Sql::SelectClause.new(engine)) }.join(', ')}", "FROM #{table_sql}", (joins unless joins.blank? ), ("WHERE #{selects.collect { |s| s.to_sql(Sql::WhereClause.new(engine)) }.join("\n\tAND ")}" unless selects.blank? ), diff --git a/lib/active_relation/sql.rb b/lib/active_relation/sql.rb index 3a773fdf6e..0b9b0fc18b 100644 --- a/lib/active_relation/sql.rb +++ b/lib/active_relation/sql.rb @@ -14,7 +14,7 @@ module ActiveRelation end end - class SelectExpression < Formatter + class SelectClause < Formatter def attribute(relation_name, attribute_name, aliaz) "#{quote_table_name(relation_name)}.#{quote_column_name(attribute_name)}" + (aliaz ? " AS #{quote(aliaz.to_s)}" : "") end @@ -22,6 +22,10 @@ module ActiveRelation def select(select_sql, aliaz) "(#{select_sql})" + (aliaz ? " AS #{quote(aliaz)}" : "") end + + def value(value) + value + end end class PassThrough < Formatter diff --git a/spec/active_relation/unit/relations/projection_spec.rb b/spec/active_relation/unit/relations/projection_spec.rb index 78766d3308..f58564840b 100644 --- a/spec/active_relation/unit/relations/projection_spec.rb +++ b/spec/active_relation/unit/relations/projection_spec.rb @@ -45,17 +45,37 @@ module ActiveRelation end describe '#to_sql' do - it "manufactures sql with a limited select clause" do - Projection.new(@relation, @attribute).to_sql.should be_like(" - SELECT `users`.`id` - FROM `users` - ") + describe 'when given an attribute' do + it "manufactures sql with a limited select clause" do + Projection.new(@relation, @attribute).to_sql.should be_like(" + SELECT `users`.`id` + FROM `users` + ") + end end - it "manufactures sql with value selects" do - Projection.new(@relation, Projection.new(@relation, @relation[:name])).to_sql.should be_like(" - SELECT (SELECT `users`.`name` FROM `users`) FROM `users` - ") + describe 'when given a relation' do + before do + @scalar_relation = Projection.new(@relation, @relation[:name]) + end + + it "manufactures sql with scalar selects" do + Projection.new(@relation, @scalar_relation).to_sql.should be_like(" + SELECT (SELECT `users`.`name` FROM `users`) FROM `users` + ") + end + end + + describe 'when given a string' do + before do + @string = "asdf" + end + + it "passes the string through to the select clause" do + Projection.new(@relation, @string).to_sql.should be_like(" + SELECT asdf FROM `users` + ") + end end end end |