active_force 0.15.1 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +15 -0
- data/lib/active_force/active_query.rb +21 -32
- data/lib/active_force/association/belongs_to_association.rb +5 -1
- data/lib/active_force/association/eager_load_builder_for_nested_includes.rb +84 -0
- data/lib/active_force/association/eager_load_projection_builder.rb +15 -8
- data/lib/active_force/association/relation_model_builder.rb +10 -8
- data/lib/active_force/association.rb +1 -0
- data/lib/active_force/query.rb +30 -24
- data/lib/active_force/sobject.rb +10 -6
- data/lib/active_force/version.rb +1 -1
- data/spec/active_force/active_query_spec.rb +101 -59
- data/spec/active_force/association_spec.rb +11 -1
- data/spec/active_force/query_spec.rb +60 -5
- data/spec/active_force/sobject/includes_spec.rb +325 -0
- data/spec/active_force/sobject_spec.rb +69 -6
- data/spec/support/sobjects.rb +41 -0
- metadata +7 -6
| @@ -9,7 +9,7 @@ describe ActiveForce::ActiveQuery do | |
| 9 9 | 
             
                })
         | 
| 10 10 | 
             
              end
         | 
| 11 11 | 
             
              let(:mappings){ { id: "Id", field: "Field__c", other_field: "Other_Field" } }
         | 
| 12 | 
            -
              let(:client){ double( | 
| 12 | 
            +
              let(:client) { double('client', query: nil) }
         | 
| 13 13 | 
             
              let(:active_query){ described_class.new(sobject) }
         | 
| 14 14 | 
             
              let(:api_result) do
         | 
| 15 15 | 
             
                [
         | 
| @@ -42,48 +42,45 @@ describe ActiveForce::ActiveQuery do | |
| 42 42 |  | 
| 43 43 | 
             
              describe "select only some field using mappings" do
         | 
| 44 44 | 
             
                it "should return a query only with selected field" do
         | 
| 45 | 
            -
                  active_query.select(:field)
         | 
| 46 | 
            -
                  expect( | 
| 45 | 
            +
                  new_query = active_query.select(:field)
         | 
| 46 | 
            +
                  expect(new_query.to_s).to eq("SELECT Field__c FROM table_name")
         | 
| 47 47 | 
             
                end
         | 
| 48 48 | 
             
              end
         | 
| 49 49 |  | 
| 50 50 | 
             
              describe "condition mapping" do
         | 
| 51 51 | 
             
                it "maps conditions for a .where" do
         | 
| 52 | 
            -
                  active_query.where(field: 123)
         | 
| 53 | 
            -
                  expect( | 
| 52 | 
            +
                  new_query = active_query.where(field: 123)
         | 
| 53 | 
            +
                  expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
         | 
| 54 54 | 
             
                end
         | 
| 55 55 |  | 
| 56 56 | 
             
                it 'transforms an array to a WHERE/IN clause' do
         | 
| 57 | 
            -
                  active_query.where(field: ['foo', 'bar'])
         | 
| 58 | 
            -
                  expect( | 
| 57 | 
            +
                  new_query = active_query.where(field: ['foo', 'bar'])
         | 
| 58 | 
            +
                  expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c IN ('foo','bar'))")
         | 
| 59 59 | 
             
                end
         | 
| 60 60 |  | 
| 61 61 | 
             
                it "encloses the value in quotes if it's a string" do
         | 
| 62 | 
            -
                  active_query.where field: "hello"
         | 
| 63 | 
            -
                  expect( | 
| 62 | 
            +
                  new_query = active_query.where field: "hello"
         | 
| 63 | 
            +
                  expect(new_query.to_s).to end_with("(Field__c = 'hello')")
         | 
| 64 64 | 
             
                end
         | 
| 65 65 |  | 
| 66 66 | 
             
                it "formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if it's a DateTime" do
         | 
| 67 67 | 
             
                  value = DateTime.now
         | 
| 68 | 
            -
                  active_query.where(field: value)
         | 
| 69 | 
            -
                  expect(active_query.to_s).to end_with("(Field__c = #{value.iso8601})")
         | 
| 68 | 
            +
                  expect(active_query.where(field: value).to_s).to end_with("(Field__c = #{value.iso8601})")
         | 
| 70 69 | 
             
                end
         | 
| 71 70 |  | 
| 72 71 | 
             
                it "formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if it's a Time" do
         | 
| 73 72 | 
             
                  value = Time.now
         | 
| 74 | 
            -
                  active_query.where(field: value)
         | 
| 75 | 
            -
                  expect(active_query.to_s).to end_with("(Field__c = #{value.iso8601})")
         | 
| 73 | 
            +
                  expect(active_query.where(field: value).to_s).to end_with("(Field__c = #{value.iso8601})")
         | 
| 76 74 | 
             
                end
         | 
| 77 75 |  | 
| 78 76 | 
             
                it "formats as YYYY-MM-DD and does not enclose in quotes if it's a Date" do
         | 
| 79 77 | 
             
                  value = Date.today
         | 
| 80 | 
            -
                  active_query.where(field: value)
         | 
| 81 | 
            -
                  expect(active_query.to_s).to end_with("(Field__c = #{value.iso8601})")
         | 
| 78 | 
            +
                  expect(active_query.where(field: value).to_s).to end_with("(Field__c = #{value.iso8601})")
         | 
| 82 79 | 
             
                end
         | 
| 83 80 |  | 
| 84 81 | 
             
                it "puts NULL when a field is set as nil" do
         | 
| 85 | 
            -
                  active_query.where field: nil
         | 
| 86 | 
            -
                  expect( | 
| 82 | 
            +
                  new_query = active_query.where field: nil
         | 
| 83 | 
            +
                  expect(new_query.to_s).to end_with("(Field__c = NULL)")
         | 
| 87 84 | 
             
                end
         | 
| 88 85 |  | 
| 89 86 | 
             
                describe 'bind parameters' do
         | 
| @@ -95,36 +92,33 @@ describe ActiveForce::ActiveQuery do | |
| 95 92 | 
             
                  end
         | 
| 96 93 |  | 
| 97 94 | 
             
                  it 'accepts bind parameters' do
         | 
| 98 | 
            -
                    active_query.where('Field__c = ?', 123)
         | 
| 99 | 
            -
                    expect( | 
| 95 | 
            +
                    new_query = active_query.where('Field__c = ?', 123)
         | 
| 96 | 
            +
                    expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
         | 
| 100 97 | 
             
                  end
         | 
| 101 98 |  | 
| 102 99 | 
             
                  it 'accepts nil bind parameters' do
         | 
| 103 | 
            -
                    active_query.where('Field__c = ?', nil)
         | 
| 104 | 
            -
                    expect( | 
| 100 | 
            +
                    new_query = active_query.where('Field__c = ?', nil)
         | 
| 101 | 
            +
                    expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = NULL)")
         | 
| 105 102 | 
             
                  end
         | 
| 106 103 |  | 
| 107 104 | 
             
                  it 'accepts multiple bind parameters' do
         | 
| 108 | 
            -
                    active_query.where('Field__c = ? AND Other_Field__c = ? AND Name = ?', 123, 321, 'Bob')
         | 
| 109 | 
            -
                    expect( | 
| 105 | 
            +
                    new_query = active_query.where('Field__c = ? AND Other_Field__c = ? AND Name = ?', 123, 321, 'Bob')
         | 
| 106 | 
            +
                    expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
         | 
| 110 107 | 
             
                  end
         | 
| 111 108 |  | 
| 112 109 | 
             
                  it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a DateTime' do
         | 
| 113 110 | 
             
                    value = DateTime.now
         | 
| 114 | 
            -
                    active_query.where('Field__c > ?', value)
         | 
| 115 | 
            -
                    expect(active_query.to_s).to end_with("(Field__c > #{value.iso8601})")
         | 
| 111 | 
            +
                    expect(active_query.where('Field__c > ?', value).to_s).to end_with("(Field__c > #{value.iso8601})")
         | 
| 116 112 | 
             
                  end
         | 
| 117 113 |  | 
| 118 114 | 
             
                  it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a Time' do
         | 
| 119 115 | 
             
                    value = Time.now
         | 
| 120 | 
            -
                    active_query.where('Field__c > ?', value)
         | 
| 121 | 
            -
                    expect(active_query.to_s).to end_with("(Field__c > #{value.iso8601})")
         | 
| 116 | 
            +
                    expect(active_query.where('Field__c > ?', value).to_s).to end_with("(Field__c > #{value.iso8601})")
         | 
| 122 117 | 
             
                  end
         | 
| 123 118 |  | 
| 124 119 | 
             
                  it 'formats as YYYY-MM-DD and does not enclose in quotes if value is a Date' do
         | 
| 125 120 | 
             
                    value = Date.today
         | 
| 126 | 
            -
                    active_query.where('Field__c > ?', value)
         | 
| 127 | 
            -
                    expect(active_query.to_s).to end_with("(Field__c > #{value.iso8601})")
         | 
| 121 | 
            +
                    expect(active_query.where('Field__c > ?', value).to_s).to end_with("(Field__c > #{value.iso8601})")
         | 
| 128 122 | 
             
                  end
         | 
| 129 123 |  | 
| 130 124 | 
             
                  it 'complains when there given an incorrect number of bind parameters' do
         | 
| @@ -135,41 +129,41 @@ describe ActiveForce::ActiveQuery do | |
| 135 129 |  | 
| 136 130 | 
             
                  context 'named bind parameters' do
         | 
| 137 131 | 
             
                    it 'accepts bind parameters' do
         | 
| 138 | 
            -
                      active_query.where('Field__c = :field', field: 123)
         | 
| 139 | 
            -
                      expect( | 
| 132 | 
            +
                      new_query = active_query.where('Field__c = :field', field: 123)
         | 
| 133 | 
            +
                      expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123)")
         | 
| 140 134 | 
             
                    end
         | 
| 141 135 |  | 
| 142 136 | 
             
                    it 'accepts nil bind parameters' do
         | 
| 143 | 
            -
                      active_query.where('Field__c = :field', field: nil)
         | 
| 144 | 
            -
                      expect( | 
| 137 | 
            +
                      new_query = active_query.where('Field__c = :field', field: nil)
         | 
| 138 | 
            +
                      expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = NULL)")
         | 
| 145 139 | 
             
                    end
         | 
| 146 140 |  | 
| 147 141 | 
             
                    it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a DateTime' do
         | 
| 148 142 | 
             
                      value = DateTime.now
         | 
| 149 | 
            -
                      active_query.where('Field__c < :field', field: value)
         | 
| 150 | 
            -
                      expect( | 
| 143 | 
            +
                      new_query = active_query.where('Field__c < :field', field: value)
         | 
| 144 | 
            +
                      expect(new_query.to_s).to end_with("(Field__c < #{value.iso8601})")
         | 
| 151 145 | 
             
                    end
         | 
| 152 146 |  | 
| 153 147 | 
             
                    it 'formats as YYYY-MM-DDThh:mm:ss-hh:mm and does not enclose in quotes if value is a Time' do
         | 
| 154 148 | 
             
                      value = Time.now
         | 
| 155 | 
            -
                      active_query.where('Field__c < :field', field: value)
         | 
| 156 | 
            -
                      expect( | 
| 149 | 
            +
                      new_query = active_query.where('Field__c < :field', field: value)
         | 
| 150 | 
            +
                      expect(new_query.to_s).to end_with("(Field__c < #{value.iso8601})")
         | 
| 157 151 | 
             
                    end
         | 
| 158 152 |  | 
| 159 153 | 
             
                    it 'formats as YYYY-MM-DD and does not enclose in quotes if value is a Date' do
         | 
| 160 154 | 
             
                      value = Date.today
         | 
| 161 | 
            -
                      active_query.where('Field__c < :field', field: value)
         | 
| 162 | 
            -
                      expect( | 
| 155 | 
            +
                      new_query = active_query.where('Field__c < :field', field: value)
         | 
| 156 | 
            +
                      expect(new_query.to_s).to end_with("(Field__c < #{value.iso8601})")
         | 
| 163 157 | 
             
                    end
         | 
| 164 158 |  | 
| 165 159 | 
             
                    it 'accepts multiple bind parameters' do
         | 
| 166 | 
            -
                      active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', field: 123, other_field: 321, name: 'Bob')
         | 
| 167 | 
            -
                      expect( | 
| 160 | 
            +
                      new_query = active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', field: 123, other_field: 321, name: 'Bob')
         | 
| 161 | 
            +
                      expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
         | 
| 168 162 | 
             
                    end
         | 
| 169 163 |  | 
| 170 164 | 
             
                    it 'accepts multiple bind parameters orderless' do
         | 
| 171 | 
            -
                      active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', name: 'Bob', other_field: 321, field: 123)
         | 
| 172 | 
            -
                      expect( | 
| 165 | 
            +
                      new_query = active_query.where('Field__c = :field AND Other_Field__c = :other_field AND Name = :name', name: 'Bob', other_field: 321, field: 123)
         | 
| 166 | 
            +
                      expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Field__c = 123 AND Other_Field__c = 321 AND Name = 'Bob')")
         | 
| 173 167 | 
             
                    end
         | 
| 174 168 |  | 
| 175 169 | 
             
                    it 'complains when there given an incorrect number of bind parameters' do
         | 
| @@ -198,29 +192,77 @@ describe ActiveForce::ActiveQuery do | |
| 198 192 | 
             
                    {"Id" => "0000000000EEEEEFFF"}
         | 
| 199 193 | 
             
                  ]
         | 
| 200 194 | 
             
                end
         | 
| 195 | 
            +
             | 
| 201 196 | 
             
                it 'allows method chaining' do
         | 
| 202 197 | 
             
                  result = active_query.where("Text_Label = 'foo'").where("Checkbox_Label = true")
         | 
| 203 198 | 
             
                  expect(result).to be_a described_class
         | 
| 204 199 | 
             
                end
         | 
| 205 200 |  | 
| 201 | 
            +
                it 'does not execute a query' do
         | 
| 202 | 
            +
                  active_query.where('x')
         | 
| 203 | 
            +
                  expect(client).not_to have_received(:query)
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                context 'when calling `where` on an ActiveQuery object that already has records' do
         | 
| 207 | 
            +
                  context 'after the query result has been decorated' do
         | 
| 208 | 
            +
                    it 'returns a new ActiveQuery object' do
         | 
| 209 | 
            +
                      first_active_query = active_query.where("Text_Label = 'foo'")
         | 
| 210 | 
            +
                      first_active_query.to_a # decorates the results
         | 
| 211 | 
            +
                      second_active_query = first_active_query.where("Checkbox_Label = true")
         | 
| 212 | 
            +
                      second_active_query.to_a
         | 
| 213 | 
            +
                      expect(second_active_query).to be_a described_class
         | 
| 214 | 
            +
                      expect(second_active_query).not_to eq first_active_query
         | 
| 215 | 
            +
                      expect(second_active_query.to_s).not_to eq first_active_query.to_s
         | 
| 216 | 
            +
                      expect(second_active_query.to_a.size).to eq(1)
         | 
| 217 | 
            +
                    end
         | 
| 218 | 
            +
                  end
         | 
| 219 | 
            +
                end
         | 
| 220 | 
            +
             | 
| 206 221 | 
             
                context 'when calling `where` on an ActiveQuery object that already has records' do
         | 
| 207 | 
            -
                   | 
| 208 | 
            -
             | 
| 209 | 
            -
                     | 
| 210 | 
            -
             | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 222 | 
            +
                  context 'without the query result being decorated' do
         | 
| 223 | 
            +
             | 
| 224 | 
            +
                    it 'returns a new ActiveQuery object' do
         | 
| 225 | 
            +
                      first_active_query = active_query.where("Text_Label = 'foo'")
         | 
| 226 | 
            +
                      second_active_query = first_active_query.where("Checkbox_Label = true")
         | 
| 227 | 
            +
                      expect(second_active_query).to be_a described_class
         | 
| 228 | 
            +
                      expect(second_active_query).not_to eq first_active_query
         | 
| 229 | 
            +
                      expect(second_active_query.to_s).not_to eq first_active_query.to_s
         | 
| 230 | 
            +
                      expect(second_active_query.to_a.size).to eq(1)
         | 
| 231 | 
            +
                    end
         | 
| 214 232 | 
             
                  end
         | 
| 215 233 | 
             
                end
         | 
| 234 | 
            +
              end
         | 
| 216 235 |  | 
| 236 | 
            +
              describe '#not' do
         | 
| 237 | 
            +
                it 'adds a not condition' do
         | 
| 238 | 
            +
                  expect(active_query.not(field: 'x').to_s).to end_with("WHERE (NOT ((Field__c = 'x')))")
         | 
| 239 | 
            +
                end
         | 
| 240 | 
            +
             | 
| 241 | 
            +
                it 'allows chaining' do
         | 
| 242 | 
            +
                  expect(active_query.where(field: 'x').not(field: 'y').where(field: 'z')).to be_a(described_class)
         | 
| 243 | 
            +
                end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
                it 'does not mutate the original query' do
         | 
| 246 | 
            +
                  original = active_query.to_s
         | 
| 247 | 
            +
                  active_query.not(field: 'x')
         | 
| 248 | 
            +
                  expect(active_query.to_s).to eq(original)
         | 
| 249 | 
            +
                end
         | 
| 250 | 
            +
             | 
| 251 | 
            +
                it 'returns the original query if not given a condition' do
         | 
| 252 | 
            +
                  expect(active_query.not).to be(active_query)
         | 
| 253 | 
            +
                end
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                it 'does not execute a query' do
         | 
| 256 | 
            +
                  active_query.not(field: 'x')
         | 
| 257 | 
            +
                  expect(client).not_to have_received(:query)
         | 
| 258 | 
            +
                end
         | 
| 217 259 | 
             
              end
         | 
| 218 260 |  | 
| 219 261 | 
             
              describe "#find_by" do
         | 
| 220 262 | 
             
                it "should query the client, with the SFDC field names and correctly enclosed values" do
         | 
| 221 | 
            -
                  expect(client).to receive | 
| 222 | 
            -
                  active_query.find_by field: 123
         | 
| 223 | 
            -
                  expect( | 
| 263 | 
            +
                  expect(client).to receive(:query).with("SELECT Id FROM table_name WHERE (Field__c = 123) LIMIT 1")
         | 
| 264 | 
            +
                  new_query = active_query.find_by field: 123
         | 
| 265 | 
            +
                  expect(new_query).to be_nil
         | 
| 224 266 | 
             
                end
         | 
| 225 267 | 
             
              end
         | 
| 226 268 |  | 
| @@ -290,18 +332,18 @@ describe ActiveForce::ActiveQuery do | |
| 290 332 | 
             
                let(:expected_query){ "SELECT Id FROM table_name WHERE (Backslash_Field__c = '\\\\' AND NumberField = 123 AND QuoteField = '\\' OR Id!=NULL OR Id=\\'')" }
         | 
| 291 333 |  | 
| 292 334 | 
             
                it 'escapes quotes and backslashes in bind parameters' do
         | 
| 293 | 
            -
                  active_query.where('Backslash_Field__c = :backslash_field AND NumberField = :number_field AND QuoteField = :quote_field', number_field: number_input, backslash_field: backslash_input, quote_field: quote_input)
         | 
| 294 | 
            -
                  expect( | 
| 335 | 
            +
                  new_query = active_query.where('Backslash_Field__c = :backslash_field AND NumberField = :number_field AND QuoteField = :quote_field', number_field: number_input, backslash_field: backslash_input, quote_field: quote_input)
         | 
| 336 | 
            +
                  expect(new_query.to_s).to eq(expected_query)
         | 
| 295 337 | 
             
                end
         | 
| 296 338 |  | 
| 297 339 | 
             
                it 'escapes quotes and backslashes in named bind parameters' do
         | 
| 298 | 
            -
                  active_query.where('Backslash_Field__c = ? AND NumberField = ? AND QuoteField = ?', backslash_input, number_input, quote_input)
         | 
| 299 | 
            -
                  expect( | 
| 340 | 
            +
                  new_query = active_query.where('Backslash_Field__c = ? AND NumberField = ? AND QuoteField = ?', backslash_input, number_input, quote_input)
         | 
| 341 | 
            +
                  expect(new_query.to_s).to eq(expected_query)
         | 
| 300 342 | 
             
                end
         | 
| 301 343 |  | 
| 302 344 | 
             
                it 'escapes quotes and backslashes in hash conditions' do
         | 
| 303 | 
            -
                  active_query.where(backslash_field: backslash_input, number_field: number_input, quote_field: quote_input)
         | 
| 304 | 
            -
                  expect( | 
| 345 | 
            +
                  new_query = active_query.where(backslash_field: backslash_input, number_field: number_input, quote_field: quote_input)
         | 
| 346 | 
            +
                  expect(new_query.to_s).to eq("SELECT Id FROM table_name WHERE (Backslash_Field__c = '\\\\') AND (NumberField = 123) AND (QuoteField = '\\' OR Id!=NULL OR Id=\\'')")
         | 
| 305 347 | 
             
                end
         | 
| 306 348 | 
             
              end
         | 
| 307 349 |  | 
| @@ -40,6 +40,16 @@ describe ActiveForce::SObject do | |
| 40 40 | 
             
                  post.comments.to_a
         | 
| 41 41 | 
             
                end
         | 
| 42 42 |  | 
| 43 | 
            +
                it 'is not mutated by #where' do
         | 
| 44 | 
            +
                  post.comments.where(body: 'test').to_a
         | 
| 45 | 
            +
                  expect(post.comments.to_s).to end_with("FROM Comment__c WHERE (PostId = '1')")
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                it 'is not mutated by #none' do
         | 
| 49 | 
            +
                  post.comments.none.to_a
         | 
| 50 | 
            +
                  expect(post.comments.to_s).to end_with("FROM Comment__c WHERE (PostId = '1')")
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 43 53 | 
             
                describe 'to_s' do
         | 
| 44 54 | 
             
                  it "should return a SOQL statment" do
         | 
| 45 55 | 
             
                    soql = "SELECT Id, PostId, PosterId__c, FancyPostId, Body__c FROM Comment__c WHERE (PostId = '1')"
         | 
| @@ -376,7 +386,7 @@ describe ActiveForce::SObject do | |
| 376 386 | 
             
                it 'allows passing a foreign key' do
         | 
| 377 387 | 
             
                  Comment.belongs_to :post, foreign_key: :fancy_post_id
         | 
| 378 388 | 
             
                  allow(comment).to receive(:fancy_post_id).and_return "2"
         | 
| 379 | 
            -
                  expect(client).to receive(:query).with("SELECT Id, Title__c FROM Post__c WHERE (Id = '2') LIMIT 1")
         | 
| 389 | 
            +
                  expect(client).to receive(:query).with("SELECT Id, Title__c, BlogId FROM Post__c WHERE (Id = '2') LIMIT 1")
         | 
| 380 390 | 
             
                  comment.post
         | 
| 381 391 | 
             
                  Comment.belongs_to :post # reset association to original value
         | 
| 382 392 | 
             
                end
         | 
| @@ -32,7 +32,7 @@ describe ActiveForce::Query do | |
| 32 32 | 
             
                  expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 33 33 | 
             
                end
         | 
| 34 34 |  | 
| 35 | 
            -
                it "should ignore  | 
| 35 | 
            +
                it "should ignore duplicated attributes in select statment" do
         | 
| 36 36 | 
             
                  query.fields ['Id', 'name', 'etc']
         | 
| 37 37 | 
             
                  expect(query.all.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 38 38 | 
             
                end
         | 
| @@ -46,6 +46,19 @@ describe ActiveForce::Query do | |
| 46 46 | 
             
                it "should add multiples conditions to a query with parentheses" do
         | 
| 47 47 | 
             
                  expect(query.where("condition1 = 1").where("condition2 = 2 OR condition3 = 3").to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (condition1 = 1) AND (condition2 = 2 OR condition3 = 3)"
         | 
| 48 48 | 
             
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                it "should not duplicate conditions" do
         | 
| 51 | 
            +
                  first_query = query.where("name = 'cool'").where("foo = 'baz'")
         | 
| 52 | 
            +
                  second_query = first_query.where("name = 'cool'")
         | 
| 53 | 
            +
                  expect(first_query.to_s).to eq(second_query.to_s)
         | 
| 54 | 
            +
                  expect(first_query.object_id).to eq(second_query.object_id)
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                it "should not update the original query" do
         | 
| 58 | 
            +
                  new_query = query.where("name = 'cool'")
         | 
| 59 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 60 | 
            +
                  expect(new_query.to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (name = 'cool')"
         | 
| 61 | 
            +
                end
         | 
| 49 62 | 
             
              end
         | 
| 50 63 |  | 
| 51 64 | 
             
              describe ".not" do
         | 
| @@ -68,12 +81,18 @@ describe ActiveForce::Query do | |
| 68 81 | 
             
                it "should add a limit to a query" do
         | 
| 69 82 | 
             
                  expect(query.limit("25").to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
         | 
| 70 83 | 
             
                end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                it "should not update the original query" do
         | 
| 86 | 
            +
                  new_query = query.limit("25")
         | 
| 87 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 88 | 
            +
                  expect(new_query.to_s).to eq "SELECT Id, name, etc FROM table_name LIMIT 25"
         | 
| 89 | 
            +
                end
         | 
| 71 90 | 
             
              end
         | 
| 72 91 |  | 
| 73 92 | 
             
              describe ".limit_value" do
         | 
| 74 93 | 
             
                it "should return the limit value" do
         | 
| 75 | 
            -
                  query.limit(4)
         | 
| 76 | 
            -
                  expect( | 
| 94 | 
            +
                  new_query = query.limit(4)
         | 
| 95 | 
            +
                  expect(new_query.limit_value).to eq 4
         | 
| 77 96 | 
             
                end
         | 
| 78 97 | 
             
              end
         | 
| 79 98 |  | 
| @@ -81,12 +100,18 @@ describe ActiveForce::Query do | |
| 81 100 | 
             
                it "should add an offset to a query" do
         | 
| 82 101 | 
             
                  expect(query.offset(4).to_s).to eq "SELECT Id, name, etc FROM table_name OFFSET 4"
         | 
| 83 102 | 
             
                end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                it "should not update the original query" do
         | 
| 105 | 
            +
                  new_query = query.offset(4)
         | 
| 106 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 107 | 
            +
                  expect(new_query.to_s).to eq "SELECT Id, name, etc FROM table_name OFFSET 4"
         | 
| 108 | 
            +
                end
         | 
| 84 109 | 
             
              end
         | 
| 85 110 |  | 
| 86 111 | 
             
              describe ".offset_value" do
         | 
| 87 112 | 
             
                it "should return the offset value" do
         | 
| 88 | 
            -
                  query.offset(4)
         | 
| 89 | 
            -
                  expect( | 
| 113 | 
            +
                  new_query = query.offset(4)
         | 
| 114 | 
            +
                  expect(new_query.offset_value).to eq 4
         | 
| 90 115 | 
             
                end
         | 
| 91 116 | 
             
              end
         | 
| 92 117 |  | 
| @@ -104,6 +129,12 @@ describe ActiveForce::Query do | |
| 104 129 | 
             
                it "should add a order condition in the statment with WHERE and LIMIT" do
         | 
| 105 130 | 
             
                  expect(query.where("condition1 = 1").order("name desc").limit(1).to_s).to eq "SELECT Id, name, etc FROM table_name WHERE (condition1 = 1) ORDER BY name desc LIMIT 1"
         | 
| 106 131 | 
             
                end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
                it "should not update the original query" do
         | 
| 134 | 
            +
                  ordered_query = query.order("name desc")
         | 
| 135 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 136 | 
            +
                  expect(ordered_query.to_s).to eq "SELECT Id, name, etc FROM table_name ORDER BY name desc"
         | 
| 137 | 
            +
                end
         | 
| 107 138 | 
             
              end
         | 
| 108 139 |  | 
| 109 140 | 
             
              describe '.join' do
         | 
| @@ -116,18 +147,36 @@ describe ActiveForce::Query do | |
| 116 147 | 
             
                it 'should add another select statment on the current select' do
         | 
| 117 148 | 
             
                  expect(query.join(join_query).to_s).to eq 'SELECT Id, name, etc, (SELECT Id, name, etc FROM join_table_name) FROM table_name'
         | 
| 118 149 | 
             
                end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                it "should not update the original query" do
         | 
| 152 | 
            +
                  new_query = query.join(join_query)
         | 
| 153 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 154 | 
            +
                  expect(new_query.to_s).to eq 'SELECT Id, name, etc, (SELECT Id, name, etc FROM join_table_name) FROM table_name'
         | 
| 155 | 
            +
                end
         | 
| 119 156 | 
             
              end
         | 
| 120 157 |  | 
| 121 158 | 
             
              describe '.first' do
         | 
| 122 159 | 
             
                it 'should return the query for the first record' do
         | 
| 123 160 | 
             
                  expect(query.first.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
         | 
| 124 161 | 
             
                end
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                it "should not update the original query" do
         | 
| 164 | 
            +
                  new_query = query.first
         | 
| 165 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 166 | 
            +
                  expect(new_query.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
         | 
| 167 | 
            +
                end
         | 
| 125 168 | 
             
              end
         | 
| 126 169 |  | 
| 127 170 | 
             
              describe '.last' do
         | 
| 128 171 | 
             
                it 'should return the query for the last record' do
         | 
| 129 172 | 
             
                  expect(query.last.to_s).to eq 'SELECT Id, name, etc FROM table_name ORDER BY Id DESC LIMIT 1'
         | 
| 130 173 | 
             
                end
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                it "should not update the original query" do
         | 
| 176 | 
            +
                  new_query = query.last
         | 
| 177 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 178 | 
            +
                  expect(new_query.to_s).to eq 'SELECT Id, name, etc FROM table_name ORDER BY Id DESC LIMIT 1'
         | 
| 179 | 
            +
                end
         | 
| 131 180 | 
             
              end
         | 
| 132 181 |  | 
| 133 182 | 
             
              describe ".count" do
         | 
| @@ -138,6 +187,12 @@ describe ActiveForce::Query do | |
| 138 187 | 
             
                it "should work with a condition" do
         | 
| 139 188 | 
             
                  expect(query.where("name = 'cool'").count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
         | 
| 140 189 | 
             
                end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                it "should not update the original query" do
         | 
| 192 | 
            +
                  query_with_count = query.where("name = 'cool'").count
         | 
| 193 | 
            +
                  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
         | 
| 194 | 
            +
                  expect(query_with_count.to_s).to eq "SELECT count(Id) FROM table_name WHERE (name = 'cool')"
         | 
| 195 | 
            +
                end
         | 
| 141 196 | 
             
              end
         | 
| 142 197 |  | 
| 143 198 | 
             
              describe ".sum" do
         |