PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/rails/activerecord/test/base_test.rb

http://monkeycharger.googlecode.com/
Ruby | 1718 lines | 1510 code | 163 blank | 45 comment | 11 complexity | 64c14dc85223b53be05b7eeda8a5a16c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. require 'abstract_unit'
  2. require 'fixtures/topic'
  3. require 'fixtures/reply'
  4. require 'fixtures/company'
  5. require 'fixtures/customer'
  6. require 'fixtures/developer'
  7. require 'fixtures/project'
  8. require 'fixtures/default'
  9. require 'fixtures/auto_id'
  10. require 'fixtures/column_name'
  11. require 'fixtures/subscriber'
  12. require 'fixtures/keyboard'
  13. require 'fixtures/post'
  14. class Category < ActiveRecord::Base; end
  15. class Smarts < ActiveRecord::Base; end
  16. class CreditCard < ActiveRecord::Base
  17. class PinNumber < ActiveRecord::Base
  18. class CvvCode < ActiveRecord::Base; end
  19. class SubCvvCode < CvvCode; end
  20. end
  21. class SubPinNumber < PinNumber; end
  22. class Brand < Category; end
  23. end
  24. class MasterCreditCard < ActiveRecord::Base; end
  25. class Post < ActiveRecord::Base; end
  26. class Computer < ActiveRecord::Base; end
  27. class NonExistentTable < ActiveRecord::Base; end
  28. class TestOracleDefault < ActiveRecord::Base; end
  29. class LoosePerson < ActiveRecord::Base
  30. self.table_name = 'people'
  31. self.abstract_class = true
  32. attr_protected :credit_rating, :administrator
  33. end
  34. class LooseDescendant < LoosePerson
  35. attr_protected :phone_number
  36. end
  37. class TightPerson < ActiveRecord::Base
  38. self.table_name = 'people'
  39. attr_accessible :name, :address
  40. end
  41. class TightDescendant < TightPerson
  42. attr_accessible :phone_number
  43. end
  44. class Booleantest < ActiveRecord::Base; end
  45. class Task < ActiveRecord::Base
  46. attr_protected :starting
  47. end
  48. class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
  49. self.table_name = 'topics'
  50. attr_accessible :author_name
  51. attr_protected :content
  52. end
  53. class BasicsTest < Test::Unit::TestCase
  54. fixtures :topics, :companies, :developers, :projects, :computers, :accounts
  55. def test_table_exists
  56. assert !NonExistentTable.table_exists?
  57. assert Topic.table_exists?
  58. end
  59. def test_set_attributes
  60. topic = Topic.find(1)
  61. topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
  62. topic.save
  63. assert_equal("Budget", topic.title)
  64. assert_equal("Jason", topic.author_name)
  65. assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
  66. end
  67. def test_integers_as_nil
  68. test = AutoId.create('value' => '')
  69. assert_nil AutoId.find(test.id).value
  70. end
  71. def test_set_attributes_with_block
  72. topic = Topic.new do |t|
  73. t.title = "Budget"
  74. t.author_name = "Jason"
  75. end
  76. assert_equal("Budget", topic.title)
  77. assert_equal("Jason", topic.author_name)
  78. end
  79. def test_respond_to?
  80. topic = Topic.find(1)
  81. assert topic.respond_to?("title")
  82. assert topic.respond_to?("title?")
  83. assert topic.respond_to?("title=")
  84. assert topic.respond_to?(:title)
  85. assert topic.respond_to?(:title?)
  86. assert topic.respond_to?(:title=)
  87. assert topic.respond_to?("author_name")
  88. assert topic.respond_to?("attribute_names")
  89. assert !topic.respond_to?("nothingness")
  90. assert !topic.respond_to?(:nothingness)
  91. end
  92. def test_array_content
  93. topic = Topic.new
  94. topic.content = %w( one two three )
  95. topic.save
  96. assert_equal(%w( one two three ), Topic.find(topic.id).content)
  97. end
  98. def test_hash_content
  99. topic = Topic.new
  100. topic.content = { "one" => 1, "two" => 2 }
  101. topic.save
  102. assert_equal 2, Topic.find(topic.id).content["two"]
  103. topic.content["three"] = 3
  104. topic.save
  105. assert_equal 3, Topic.find(topic.id).content["three"]
  106. end
  107. def test_update_array_content
  108. topic = Topic.new
  109. topic.content = %w( one two three )
  110. topic.content.push "four"
  111. assert_equal(%w( one two three four ), topic.content)
  112. topic.save
  113. topic = Topic.find(topic.id)
  114. topic.content << "five"
  115. assert_equal(%w( one two three four five ), topic.content)
  116. end
  117. def test_case_sensitive_attributes_hash
  118. # DB2 is not case-sensitive
  119. return true if current_adapter?(:DB2Adapter)
  120. assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.find(:first).attributes
  121. end
  122. def test_create
  123. topic = Topic.new
  124. topic.title = "New Topic"
  125. topic.save
  126. topic_reloaded = Topic.find(topic.id)
  127. assert_equal("New Topic", topic_reloaded.title)
  128. end
  129. def test_save!
  130. topic = Topic.new(:title => "New Topic")
  131. assert topic.save!
  132. reply = Reply.new
  133. assert_raise(ActiveRecord::RecordInvalid) { reply.save! }
  134. end
  135. def test_save_null_string_attributes
  136. topic = Topic.find(1)
  137. topic.attributes = { "title" => "null", "author_name" => "null" }
  138. topic.save!
  139. topic.reload
  140. assert_equal("null", topic.title)
  141. assert_equal("null", topic.author_name)
  142. end
  143. def test_save_nil_string_attributes
  144. topic = Topic.find(1)
  145. topic.title = nil
  146. topic.save!
  147. topic.reload
  148. assert_nil topic.title
  149. end
  150. def test_hashes_not_mangled
  151. new_topic = { :title => "New Topic" }
  152. new_topic_values = { :title => "AnotherTopic" }
  153. topic = Topic.new(new_topic)
  154. assert_equal new_topic[:title], topic.title
  155. topic.attributes= new_topic_values
  156. assert_equal new_topic_values[:title], topic.title
  157. end
  158. def test_create_many
  159. topics = Topic.create([ { "title" => "first" }, { "title" => "second" }])
  160. assert_equal 2, topics.size
  161. assert_equal "first", topics.first.title
  162. end
  163. def test_create_columns_not_equal_attributes
  164. topic = Topic.new
  165. topic.title = 'Another New Topic'
  166. topic.send :write_attribute, 'does_not_exist', 'test'
  167. assert_nothing_raised { topic.save }
  168. end
  169. def test_create_through_factory
  170. topic = Topic.create("title" => "New Topic")
  171. topicReloaded = Topic.find(topic.id)
  172. assert_equal(topic, topicReloaded)
  173. end
  174. def test_update
  175. topic = Topic.new
  176. topic.title = "Another New Topic"
  177. topic.written_on = "2003-12-12 23:23:00"
  178. topic.save
  179. topicReloaded = Topic.find(topic.id)
  180. assert_equal("Another New Topic", topicReloaded.title)
  181. topicReloaded.title = "Updated topic"
  182. topicReloaded.save
  183. topicReloadedAgain = Topic.find(topic.id)
  184. assert_equal("Updated topic", topicReloadedAgain.title)
  185. end
  186. def test_update_columns_not_equal_attributes
  187. topic = Topic.new
  188. topic.title = "Still another topic"
  189. topic.save
  190. topicReloaded = Topic.find(topic.id)
  191. topicReloaded.title = "A New Topic"
  192. topicReloaded.send :write_attribute, 'does_not_exist', 'test'
  193. assert_nothing_raised { topicReloaded.save }
  194. end
  195. def test_write_attribute
  196. topic = Topic.new
  197. topic.send(:write_attribute, :title, "Still another topic")
  198. assert_equal "Still another topic", topic.title
  199. topic.send(:write_attribute, "title", "Still another topic: part 2")
  200. assert_equal "Still another topic: part 2", topic.title
  201. end
  202. def test_read_attribute
  203. topic = Topic.new
  204. topic.title = "Don't change the topic"
  205. assert_equal "Don't change the topic", topic.send(:read_attribute, "title")
  206. assert_equal "Don't change the topic", topic["title"]
  207. assert_equal "Don't change the topic", topic.send(:read_attribute, :title)
  208. assert_equal "Don't change the topic", topic[:title]
  209. end
  210. def test_read_attribute_when_false
  211. topic = topics(:first)
  212. topic.approved = false
  213. assert !topic.approved?, "approved should be false"
  214. topic.approved = "false"
  215. assert !topic.approved?, "approved should be false"
  216. end
  217. def test_read_attribute_when_true
  218. topic = topics(:first)
  219. topic.approved = true
  220. assert topic.approved?, "approved should be true"
  221. topic.approved = "true"
  222. assert topic.approved?, "approved should be true"
  223. end
  224. def test_read_write_boolean_attribute
  225. topic = Topic.new
  226. # puts ""
  227. # puts "New Topic"
  228. # puts topic.inspect
  229. topic.approved = "false"
  230. # puts "Expecting false"
  231. # puts topic.inspect
  232. assert !topic.approved?, "approved should be false"
  233. topic.approved = "false"
  234. # puts "Expecting false"
  235. # puts topic.inspect
  236. assert !topic.approved?, "approved should be false"
  237. topic.approved = "true"
  238. # puts "Expecting true"
  239. # puts topic.inspect
  240. assert topic.approved?, "approved should be true"
  241. topic.approved = "true"
  242. # puts "Expecting true"
  243. # puts topic.inspect
  244. assert topic.approved?, "approved should be true"
  245. # puts ""
  246. end
  247. def test_query_attribute_string
  248. [nil, "", " "].each do |value|
  249. assert_equal false, Topic.new(:author_name => value).author_name?
  250. end
  251. assert_equal true, Topic.new(:author_name => "Name").author_name?
  252. end
  253. def test_query_attribute_number
  254. [nil, 0, "0"].each do |value|
  255. assert_equal false, Developer.new(:salary => value).salary?
  256. end
  257. assert_equal true, Developer.new(:salary => 1).salary?
  258. assert_equal true, Developer.new(:salary => "1").salary?
  259. end
  260. def test_query_attribute_boolean
  261. [nil, "", false, "false", "f", 0].each do |value|
  262. assert_equal false, Topic.new(:approved => value).approved?
  263. end
  264. [true, "true", "1", 1].each do |value|
  265. assert_equal true, Topic.new(:approved => value).approved?
  266. end
  267. end
  268. def test_query_attribute_with_custom_fields
  269. object = Company.find_by_sql(<<-SQL).first
  270. SELECT c1.*, c2.ruby_type as string_value, c2.rating as int_value
  271. FROM companies c1, companies c2
  272. WHERE c1.firm_id = c2.id
  273. AND c1.id = 2
  274. SQL
  275. assert_equal "Firm", object.string_value
  276. assert object.string_value?
  277. object.string_value = " "
  278. assert !object.string_value?
  279. assert_equal 1, object.int_value.to_i
  280. assert object.int_value?
  281. object.int_value = "0"
  282. assert !object.int_value?
  283. end
  284. def test_reader_generation
  285. Topic.find(:first).title
  286. Firm.find(:first).name
  287. Client.find(:first).name
  288. if ActiveRecord::Base.generate_read_methods
  289. assert_readers(Topic, %w(type replies_count))
  290. assert_readers(Firm, %w(type))
  291. assert_readers(Client, %w(type ruby_type rating?))
  292. else
  293. [Topic, Firm, Client].each {|klass| assert_equal klass.read_methods, {}}
  294. end
  295. end
  296. def test_reader_for_invalid_column_names
  297. # column names which aren't legal ruby ids
  298. topic = Topic.find(:first)
  299. topic.send(:define_read_method, "mumub-jumbo".to_sym, "mumub-jumbo", nil)
  300. assert !Topic.read_methods.include?("mumub-jumbo")
  301. end
  302. def test_non_attribute_access_and_assignment
  303. topic = Topic.new
  304. assert !topic.respond_to?("mumbo")
  305. assert_raises(NoMethodError) { topic.mumbo }
  306. assert_raises(NoMethodError) { topic.mumbo = 5 }
  307. end
  308. def test_preserving_date_objects
  309. # SQL Server doesn't have a separate column type just for dates, so all are returned as time
  310. return true if current_adapter?(:SQLServerAdapter)
  311. if current_adapter?(:SybaseAdapter, :OracleAdapter)
  312. # Sybase ctlib does not (yet?) support the date type; use datetime instead.
  313. # Oracle treats all dates/times as Time.
  314. assert_kind_of(
  315. Time, Topic.find(1).last_read,
  316. "The last_read attribute should be of the Time class"
  317. )
  318. else
  319. assert_kind_of(
  320. Date, Topic.find(1).last_read,
  321. "The last_read attribute should be of the Date class"
  322. )
  323. end
  324. end
  325. def test_preserving_time_objects
  326. assert_kind_of(
  327. Time, Topic.find(1).bonus_time,
  328. "The bonus_time attribute should be of the Time class"
  329. )
  330. assert_kind_of(
  331. Time, Topic.find(1).written_on,
  332. "The written_on attribute should be of the Time class"
  333. )
  334. # For adapters which support microsecond resolution.
  335. if current_adapter?(:PostgreSQLAdapter)
  336. assert_equal 11, Topic.find(1).written_on.sec
  337. assert_equal 223300, Topic.find(1).written_on.usec
  338. assert_equal 9900, Topic.find(2).written_on.usec
  339. end
  340. end
  341. def test_destroy
  342. topic = Topic.find(1)
  343. assert_equal topic, topic.destroy, 'topic.destroy did not return self'
  344. assert topic.frozen?, 'topic not frozen after destroy'
  345. assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
  346. end
  347. def test_record_not_found_exception
  348. assert_raises(ActiveRecord::RecordNotFound) { topicReloaded = Topic.find(99999) }
  349. end
  350. def test_initialize_with_attributes
  351. topic = Topic.new({
  352. "title" => "initialized from attributes", "written_on" => "2003-12-12 23:23"
  353. })
  354. assert_equal("initialized from attributes", topic.title)
  355. end
  356. def test_initialize_with_invalid_attribute
  357. begin
  358. topic = Topic.new({ "title" => "test",
  359. "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
  360. rescue ActiveRecord::MultiparameterAssignmentErrors => ex
  361. assert_equal(1, ex.errors.size)
  362. assert_equal("last_read", ex.errors[0].attribute)
  363. end
  364. end
  365. def test_load
  366. topics = Topic.find(:all, :order => 'id')
  367. assert_equal(2, topics.size)
  368. assert_equal(topics(:first).title, topics.first.title)
  369. end
  370. def test_load_with_condition
  371. topics = Topic.find(:all, :conditions => "author_name = 'Mary'")
  372. assert_equal(1, topics.size)
  373. assert_equal(topics(:second).title, topics.first.title)
  374. end
  375. def test_table_name_guesses
  376. classes = [Category, Smarts, CreditCard, CreditCard::PinNumber, CreditCard::PinNumber::CvvCode, CreditCard::SubPinNumber, CreditCard::Brand, MasterCreditCard]
  377. assert_equal "topics", Topic.table_name
  378. assert_equal "categories", Category.table_name
  379. assert_equal "smarts", Smarts.table_name
  380. assert_equal "credit_cards", CreditCard.table_name
  381. assert_equal "credit_card_pin_numbers", CreditCard::PinNumber.table_name
  382. assert_equal "credit_card_pin_number_cvv_codes", CreditCard::PinNumber::CvvCode.table_name
  383. assert_equal "credit_card_pin_numbers", CreditCard::SubPinNumber.table_name
  384. assert_equal "categories", CreditCard::Brand.table_name
  385. assert_equal "master_credit_cards", MasterCreditCard.table_name
  386. ActiveRecord::Base.pluralize_table_names = false
  387. classes.each(&:reset_table_name)
  388. assert_equal "category", Category.table_name
  389. assert_equal "smarts", Smarts.table_name
  390. assert_equal "credit_card", CreditCard.table_name
  391. assert_equal "credit_card_pin_number", CreditCard::PinNumber.table_name
  392. assert_equal "credit_card_pin_number_cvv_code", CreditCard::PinNumber::CvvCode.table_name
  393. assert_equal "credit_card_pin_number", CreditCard::SubPinNumber.table_name
  394. assert_equal "category", CreditCard::Brand.table_name
  395. assert_equal "master_credit_card", MasterCreditCard.table_name
  396. ActiveRecord::Base.pluralize_table_names = true
  397. classes.each(&:reset_table_name)
  398. ActiveRecord::Base.table_name_prefix = "test_"
  399. Category.reset_table_name
  400. assert_equal "test_categories", Category.table_name
  401. ActiveRecord::Base.table_name_suffix = "_test"
  402. Category.reset_table_name
  403. assert_equal "test_categories_test", Category.table_name
  404. ActiveRecord::Base.table_name_prefix = ""
  405. Category.reset_table_name
  406. assert_equal "categories_test", Category.table_name
  407. ActiveRecord::Base.table_name_suffix = ""
  408. Category.reset_table_name
  409. assert_equal "categories", Category.table_name
  410. ActiveRecord::Base.pluralize_table_names = false
  411. ActiveRecord::Base.table_name_prefix = "test_"
  412. Category.reset_table_name
  413. assert_equal "test_category", Category.table_name
  414. ActiveRecord::Base.table_name_suffix = "_test"
  415. Category.reset_table_name
  416. assert_equal "test_category_test", Category.table_name
  417. ActiveRecord::Base.table_name_prefix = ""
  418. Category.reset_table_name
  419. assert_equal "category_test", Category.table_name
  420. ActiveRecord::Base.table_name_suffix = ""
  421. Category.reset_table_name
  422. assert_equal "category", Category.table_name
  423. ActiveRecord::Base.pluralize_table_names = true
  424. classes.each(&:reset_table_name)
  425. end
  426. def test_destroy_all
  427. assert_equal 2, Topic.count
  428. Topic.destroy_all "author_name = 'Mary'"
  429. assert_equal 1, Topic.count
  430. end
  431. def test_destroy_many
  432. assert_equal 3, Client.count
  433. Client.destroy([2, 3])
  434. assert_equal 1, Client.count
  435. end
  436. def test_delete_many
  437. Topic.delete([1, 2])
  438. assert_equal 0, Topic.count
  439. end
  440. def test_boolean_attributes
  441. assert ! Topic.find(1).approved?
  442. assert Topic.find(2).approved?
  443. end
  444. def test_increment_counter
  445. Topic.increment_counter("replies_count", 1)
  446. assert_equal 2, Topic.find(1).replies_count
  447. Topic.increment_counter("replies_count", 1)
  448. assert_equal 3, Topic.find(1).replies_count
  449. end
  450. def test_decrement_counter
  451. Topic.decrement_counter("replies_count", 2)
  452. assert_equal -1, Topic.find(2).replies_count
  453. Topic.decrement_counter("replies_count", 2)
  454. assert_equal -2, Topic.find(2).replies_count
  455. end
  456. # The ADO library doesn't support the number of affected rows
  457. unless current_adapter?(:SQLServerAdapter)
  458. def test_update_all
  459. assert_equal 2, Topic.update_all("content = 'bulk updated!'")
  460. assert_equal "bulk updated!", Topic.find(1).content
  461. assert_equal "bulk updated!", Topic.find(2).content
  462. assert_equal 2, Topic.update_all(['content = ?', 'bulk updated again!'])
  463. assert_equal "bulk updated again!", Topic.find(1).content
  464. assert_equal "bulk updated again!", Topic.find(2).content
  465. assert_equal 2, Topic.update_all(['content = ?', nil])
  466. assert_nil Topic.find(1).content
  467. end
  468. def test_update_all_with_hash
  469. assert_not_nil Topic.find(1).last_read
  470. assert_equal 2, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
  471. assert_equal "bulk updated with hash!", Topic.find(1).content
  472. assert_equal "bulk updated with hash!", Topic.find(2).content
  473. assert_nil Topic.find(1).last_read
  474. assert_nil Topic.find(2).last_read
  475. end
  476. end
  477. if current_adapter?(:MysqlAdapter)
  478. def test_update_all_with_order_and_limit
  479. assert_equal 1, Topic.update_all("content = 'bulk updated!'", nil, :limit => 1, :order => 'id DESC')
  480. end
  481. end
  482. def test_update_many
  483. topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
  484. updated = Topic.update(topic_data.keys, topic_data.values)
  485. assert_equal 2, updated.size
  486. assert_equal "1 updated", Topic.find(1).content
  487. assert_equal "2 updated", Topic.find(2).content
  488. end
  489. def test_delete_all
  490. # The ADO library doesn't support the number of affected rows
  491. return true if current_adapter?(:SQLServerAdapter)
  492. assert_equal 2, Topic.delete_all
  493. end
  494. def test_update_by_condition
  495. Topic.update_all "content = 'bulk updated!'", ["approved = ?", true]
  496. assert_equal "Have a nice day", Topic.find(1).content
  497. assert_equal "bulk updated!", Topic.find(2).content
  498. end
  499. def test_attribute_present
  500. t = Topic.new
  501. t.title = "hello there!"
  502. t.written_on = Time.now
  503. assert t.attribute_present?("title")
  504. assert t.attribute_present?("written_on")
  505. assert !t.attribute_present?("content")
  506. end
  507. def test_attribute_keys_on_new_instance
  508. t = Topic.new
  509. assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
  510. assert_raise(NoMethodError) { t.title2 }
  511. end
  512. def test_class_name
  513. assert_equal "Firm", ActiveRecord::Base.class_name("firms")
  514. assert_equal "Category", ActiveRecord::Base.class_name("categories")
  515. assert_equal "AccountHolder", ActiveRecord::Base.class_name("account_holder")
  516. ActiveRecord::Base.pluralize_table_names = false
  517. assert_equal "Firms", ActiveRecord::Base.class_name( "firms" )
  518. ActiveRecord::Base.pluralize_table_names = true
  519. ActiveRecord::Base.table_name_prefix = "test_"
  520. assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms" )
  521. ActiveRecord::Base.table_name_suffix = "_tests"
  522. assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms_tests" )
  523. ActiveRecord::Base.table_name_prefix = ""
  524. assert_equal "Firm", ActiveRecord::Base.class_name( "firms_tests" )
  525. ActiveRecord::Base.table_name_suffix = ""
  526. assert_equal "Firm", ActiveRecord::Base.class_name( "firms" )
  527. end
  528. def test_null_fields
  529. assert_nil Topic.find(1).parent_id
  530. assert_nil Topic.create("title" => "Hey you").parent_id
  531. end
  532. def test_default_values
  533. topic = Topic.new
  534. assert topic.approved?
  535. assert_nil topic.written_on
  536. assert_nil topic.bonus_time
  537. assert_nil topic.last_read
  538. topic.save
  539. topic = Topic.find(topic.id)
  540. assert topic.approved?
  541. assert_nil topic.last_read
  542. # Oracle has some funky default handling, so it requires a bit of
  543. # extra testing. See ticket #2788.
  544. if current_adapter?(:OracleAdapter)
  545. test = TestOracleDefault.new
  546. assert_equal "X", test.test_char
  547. assert_equal "hello", test.test_string
  548. assert_equal 3, test.test_int
  549. end
  550. end
  551. # Oracle, SQLServer, and Sybase do not have a TIME datatype.
  552. unless current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
  553. def test_utc_as_time_zone
  554. Topic.default_timezone = :utc
  555. attributes = { "bonus_time" => "5:42:00AM" }
  556. topic = Topic.find(1)
  557. topic.attributes = attributes
  558. assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
  559. Topic.default_timezone = :local
  560. end
  561. def test_utc_as_time_zone_and_new
  562. Topic.default_timezone = :utc
  563. attributes = { "bonus_time(1i)"=>"2000",
  564. "bonus_time(2i)"=>"1",
  565. "bonus_time(3i)"=>"1",
  566. "bonus_time(4i)"=>"10",
  567. "bonus_time(5i)"=>"35",
  568. "bonus_time(6i)"=>"50" }
  569. topic = Topic.new(attributes)
  570. assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
  571. Topic.default_timezone = :local
  572. end
  573. end
  574. def test_default_values_on_empty_strings
  575. topic = Topic.new
  576. topic.approved = nil
  577. topic.last_read = nil
  578. topic.save
  579. topic = Topic.find(topic.id)
  580. assert_nil topic.last_read
  581. # Sybase adapter does not allow nulls in boolean columns
  582. if current_adapter?(:SybaseAdapter)
  583. assert topic.approved == false
  584. else
  585. assert_nil topic.approved
  586. end
  587. end
  588. def test_equality
  589. assert_equal Topic.find(1), Topic.find(2).topic
  590. end
  591. def test_equality_of_new_records
  592. assert_not_equal Topic.new, Topic.new
  593. end
  594. def test_hashing
  595. assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
  596. end
  597. def test_destroy_new_record
  598. client = Client.new
  599. client.destroy
  600. assert client.frozen?
  601. end
  602. def test_destroy_record_with_associations
  603. client = Client.find(3)
  604. client.destroy
  605. assert client.frozen?
  606. assert_kind_of Firm, client.firm
  607. assert_raises(TypeError) { client.name = "something else" }
  608. end
  609. def test_update_attribute
  610. assert !Topic.find(1).approved?
  611. Topic.find(1).update_attribute("approved", true)
  612. assert Topic.find(1).approved?
  613. Topic.find(1).update_attribute(:approved, false)
  614. assert !Topic.find(1).approved?
  615. end
  616. def test_update_attributes
  617. topic = Topic.find(1)
  618. assert !topic.approved?
  619. assert_equal "The First Topic", topic.title
  620. topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
  621. topic.reload
  622. assert topic.approved?
  623. assert_equal "The First Topic Updated", topic.title
  624. topic.update_attributes(:approved => false, :title => "The First Topic")
  625. topic.reload
  626. assert !topic.approved?
  627. assert_equal "The First Topic", topic.title
  628. end
  629. def test_update_attributes!
  630. reply = Reply.find(2)
  631. assert_equal "The Second Topic's of the day", reply.title
  632. assert_equal "Have a nice day", reply.content
  633. reply.update_attributes!("title" => "The Second Topic's of the day updated", "content" => "Have a nice evening")
  634. reply.reload
  635. assert_equal "The Second Topic's of the day updated", reply.title
  636. assert_equal "Have a nice evening", reply.content
  637. reply.update_attributes!(:title => "The Second Topic's of the day", :content => "Have a nice day")
  638. reply.reload
  639. assert_equal "The Second Topic's of the day", reply.title
  640. assert_equal "Have a nice day", reply.content
  641. assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") }
  642. end
  643. def test_mass_assignment_should_raise_exception_if_accessible_and_protected_attribute_writers_are_both_used
  644. topic = TopicWithProtectedContentAndAccessibleAuthorName.new
  645. assert_raises(RuntimeError) { topic.attributes = { "author_name" => "me" } }
  646. assert_raises(RuntimeError) { topic.attributes = { "content" => "stuff" } }
  647. end
  648. def test_mass_assignment_protection
  649. firm = Firm.new
  650. firm.attributes = { "name" => "Next Angle", "rating" => 5 }
  651. assert_equal 1, firm.rating
  652. end
  653. def test_mass_assignment_protection_against_class_attribute_writers
  654. [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
  655. :default_timezone, :allow_concurrency, :generate_read_methods, :schema_format, :verification_timeout, :lock_optimistically, :record_timestamps].each do |method|
  656. assert Task.respond_to?(method)
  657. assert Task.respond_to?("#{method}=")
  658. assert Task.new.respond_to?(method)
  659. assert !Task.new.respond_to?("#{method}=")
  660. end
  661. end
  662. def test_customized_primary_key_remains_protected
  663. subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
  664. assert_nil subscriber.id
  665. keyboard = Keyboard.new(:key_number => 9, :name => 'nice try')
  666. assert_nil keyboard.id
  667. end
  668. def test_customized_primary_key_remains_protected_when_refered_to_as_id
  669. subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try')
  670. assert_nil subscriber.id
  671. keyboard = Keyboard.new(:id => 9, :name => 'nice try')
  672. assert_nil keyboard.id
  673. end
  674. def test_mass_assignment_protection_on_defaults
  675. firm = Firm.new
  676. firm.attributes = { "id" => 5, "type" => "Client" }
  677. assert_nil firm.id
  678. assert_equal "Firm", firm[:type]
  679. end
  680. def test_mass_assignment_accessible
  681. reply = Reply.new("title" => "hello", "content" => "world", "approved" => true)
  682. reply.save
  683. assert reply.approved?
  684. reply.approved = false
  685. reply.save
  686. assert !reply.approved?
  687. end
  688. def test_mass_assignment_protection_inheritance
  689. assert_nil LoosePerson.accessible_attributes
  690. assert_equal [ :credit_rating, :administrator ], LoosePerson.protected_attributes
  691. assert_nil LooseDescendant.accessible_attributes
  692. assert_equal [ :credit_rating, :administrator, :phone_number ], LooseDescendant.protected_attributes
  693. assert_nil TightPerson.protected_attributes
  694. assert_equal [ :name, :address ], TightPerson.accessible_attributes
  695. assert_nil TightDescendant.protected_attributes
  696. assert_equal [ :name, :address, :phone_number ], TightDescendant.accessible_attributes
  697. end
  698. def test_multiparameter_attributes_on_date
  699. attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" }
  700. topic = Topic.find(1)
  701. topic.attributes = attributes
  702. # note that extra #to_date call allows test to pass for Oracle, which
  703. # treats dates/times the same
  704. assert_date_from_db Date.new(2004, 6, 24), topic.last_read.to_date
  705. end
  706. def test_multiparameter_attributes_on_date_with_empty_date
  707. attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "" }
  708. topic = Topic.find(1)
  709. topic.attributes = attributes
  710. # note that extra #to_date call allows test to pass for Oracle, which
  711. # treats dates/times the same
  712. assert_date_from_db Date.new(2004, 6, 1), topic.last_read.to_date
  713. end
  714. def test_multiparameter_attributes_on_date_with_all_empty
  715. attributes = { "last_read(1i)" => "", "last_read(2i)" => "", "last_read(3i)" => "" }
  716. topic = Topic.find(1)
  717. topic.attributes = attributes
  718. assert_nil topic.last_read
  719. end
  720. def test_multiparameter_attributes_on_time
  721. attributes = {
  722. "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
  723. "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00"
  724. }
  725. topic = Topic.find(1)
  726. topic.attributes = attributes
  727. assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
  728. end
  729. def test_multiparameter_attributes_on_time_with_empty_seconds
  730. attributes = {
  731. "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24",
  732. "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => ""
  733. }
  734. topic = Topic.find(1)
  735. topic.attributes = attributes
  736. assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on
  737. end
  738. def test_multiparameter_mass_assignment_protector
  739. task = Task.new
  740. time = Time.mktime(2000, 1, 1, 1)
  741. task.starting = time
  742. attributes = { "starting(1i)" => "2004", "starting(2i)" => "6", "starting(3i)" => "24" }
  743. task.attributes = attributes
  744. assert_equal time, task.starting
  745. end
  746. def test_multiparameter_assignment_of_aggregation
  747. customer = Customer.new
  748. address = Address.new("The Street", "The City", "The Country")
  749. attributes = { "address(1)" => address.street, "address(2)" => address.city, "address(3)" => address.country }
  750. customer.attributes = attributes
  751. assert_equal address, customer.address
  752. end
  753. def test_attributes_on_dummy_time
  754. # Oracle, SQL Server, and Sybase do not have a TIME datatype.
  755. return true if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
  756. attributes = {
  757. "bonus_time" => "5:42:00AM"
  758. }
  759. topic = Topic.find(1)
  760. topic.attributes = attributes
  761. assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time
  762. end
  763. def test_boolean
  764. b_false = Booleantest.create({ "value" => false })
  765. false_id = b_false.id
  766. b_true = Booleantest.create({ "value" => true })
  767. true_id = b_true.id
  768. b_false = Booleantest.find(false_id)
  769. assert !b_false.value?
  770. b_true = Booleantest.find(true_id)
  771. assert b_true.value?
  772. end
  773. def test_boolean_cast_from_string
  774. b_false = Booleantest.create({ "value" => "0" })
  775. false_id = b_false.id
  776. b_true = Booleantest.create({ "value" => "1" })
  777. true_id = b_true.id
  778. b_false = Booleantest.find(false_id)
  779. assert !b_false.value?
  780. b_true = Booleantest.find(true_id)
  781. assert b_true.value?
  782. end
  783. def test_clone
  784. topic = Topic.find(1)
  785. cloned_topic = nil
  786. assert_nothing_raised { cloned_topic = topic.clone }
  787. assert_equal topic.title, cloned_topic.title
  788. assert cloned_topic.new_record?
  789. # test if the attributes have been cloned
  790. topic.title = "a"
  791. cloned_topic.title = "b"
  792. assert_equal "a", topic.title
  793. assert_equal "b", cloned_topic.title
  794. # test if the attribute values have been cloned
  795. topic.title = {"a" => "b"}
  796. cloned_topic = topic.clone
  797. cloned_topic.title["a"] = "c"
  798. assert_equal "b", topic.title["a"]
  799. cloned_topic.save
  800. assert !cloned_topic.new_record?
  801. assert cloned_topic.id != topic.id
  802. end
  803. def test_clone_with_aggregate_of_same_name_as_attribute
  804. dev = DeveloperWithAggregate.find(1)
  805. assert_kind_of DeveloperSalary, dev.salary
  806. clone = nil
  807. assert_nothing_raised { clone = dev.clone }
  808. assert_kind_of DeveloperSalary, clone.salary
  809. assert_equal dev.salary.amount, clone.salary.amount
  810. assert clone.new_record?
  811. # test if the attributes have been cloned
  812. original_amount = clone.salary.amount
  813. dev.salary.amount = 1
  814. assert_equal original_amount, clone.salary.amount
  815. assert clone.save
  816. assert !clone.new_record?
  817. assert clone.id != dev.id
  818. end
  819. def test_clone_preserves_subtype
  820. clone = nil
  821. assert_nothing_raised { clone = Company.find(3).clone }
  822. assert_kind_of Client, clone
  823. end
  824. def test_bignum
  825. company = Company.find(1)
  826. company.rating = 2147483647
  827. company.save
  828. company = Company.find(1)
  829. assert_equal 2147483647, company.rating
  830. end
  831. # TODO: extend defaults tests to other databases!
  832. if current_adapter?(:PostgreSQLAdapter)
  833. def test_default
  834. default = Default.new
  835. # fixed dates / times
  836. assert_equal Date.new(2004, 1, 1), default.fixed_date
  837. assert_equal Time.local(2004, 1,1,0,0,0,0), default.fixed_time
  838. # char types
  839. assert_equal 'Y', default.char1
  840. assert_equal 'a varchar field', default.char2
  841. assert_equal 'a text field', default.char3
  842. end
  843. class Geometric < ActiveRecord::Base; end
  844. def test_geometric_content
  845. # accepted format notes:
  846. # ()'s aren't required
  847. # values can be a mix of float or integer
  848. g = Geometric.new(
  849. :a_point => '(5.0, 6.1)',
  850. #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
  851. :a_line_segment => '(2.0, 3), (5.5, 7.0)',
  852. :a_box => '2.0, 3, 5.5, 7.0',
  853. :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path
  854. :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))',
  855. :a_circle => '<(5.3, 10.4), 2>'
  856. )
  857. assert g.save
  858. # Reload and check that we have all the geometric attributes.
  859. h = Geometric.find(g.id)
  860. assert_equal '(5,6.1)', h.a_point
  861. assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
  862. assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
  863. assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path
  864. assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
  865. assert_equal '<(5.3,10.4),2>', h.a_circle
  866. # use a geometric function to test for an open path
  867. objs = Geometric.find_by_sql ["select isopen(a_path) from geometrics where id = ?", g.id]
  868. assert_equal objs[0].isopen, 't'
  869. # test alternate formats when defining the geometric types
  870. g = Geometric.new(
  871. :a_point => '5.0, 6.1',
  872. #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql
  873. :a_line_segment => '((2.0, 3), (5.5, 7.0))',
  874. :a_box => '(2.0, 3), (5.5, 7.0)',
  875. :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path
  876. :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0',
  877. :a_circle => '((5.3, 10.4), 2)'
  878. )
  879. assert g.save
  880. # Reload and check that we have all the geometric attributes.
  881. h = Geometric.find(g.id)
  882. assert_equal '(5,6.1)', h.a_point
  883. assert_equal '[(2,3),(5.5,7)]', h.a_line_segment
  884. assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner
  885. assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path
  886. assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon
  887. assert_equal '<(5.3,10.4),2>', h.a_circle
  888. # use a geometric function to test for an closed path
  889. objs = Geometric.find_by_sql ["select isclosed(a_path) from geometrics where id = ?", g.id]
  890. assert_equal objs[0].isclosed, 't'
  891. end
  892. end
  893. class NumericData < ActiveRecord::Base
  894. self.table_name = 'numeric_data'
  895. end
  896. def test_numeric_fields
  897. m = NumericData.new(
  898. :bank_balance => 1586.43,
  899. :big_bank_balance => BigDecimal("1000234000567.95"),
  900. :world_population => 6000000000,
  901. :my_house_population => 3
  902. )
  903. assert m.save
  904. m1 = NumericData.find(m.id)
  905. assert_not_nil m1
  906. # As with migration_test.rb, we should make world_population >= 2**62
  907. # to cover 64-bit platforms and test it is a Bignum, but the main thing
  908. # is that it's an Integer.
  909. assert_kind_of Integer, m1.world_population
  910. assert_equal 6000000000, m1.world_population
  911. assert_kind_of Fixnum, m1.my_house_population
  912. assert_equal 3, m1.my_house_population
  913. assert_kind_of BigDecimal, m1.bank_balance
  914. assert_equal BigDecimal("1586.43"), m1.bank_balance
  915. assert_kind_of BigDecimal, m1.big_bank_balance
  916. assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
  917. end
  918. def test_auto_id
  919. auto = AutoId.new
  920. auto.save
  921. assert (auto.id > 0)
  922. end
  923. def quote_column_name(name)
  924. "<#{name}>"
  925. end
  926. def test_quote_keys
  927. ar = AutoId.new
  928. source = {"foo" => "bar", "baz" => "quux"}
  929. actual = ar.send(:quote_columns, self, source)
  930. inverted = actual.invert
  931. assert_equal("<foo>", inverted["bar"])
  932. assert_equal("<baz>", inverted["quux"])
  933. end
  934. def test_sql_injection_via_find
  935. assert_raises(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
  936. Topic.find("123456 OR id > 0")
  937. end
  938. end
  939. def test_column_name_properly_quoted
  940. col_record = ColumnName.new
  941. col_record.references = 40
  942. assert col_record.save
  943. col_record.references = 41
  944. assert col_record.save
  945. assert_not_nil c2 = ColumnName.find(col_record.id)
  946. assert_equal(41, c2.references)
  947. end
  948. def test_quoting_arrays
  949. replies = Reply.find(:all, :conditions => [ "id IN (?)", topics(:first).replies.collect(&:id) ])
  950. assert_equal topics(:first).replies.size, replies.size
  951. replies = Reply.find(:all, :conditions => [ "id IN (?)", [] ])
  952. assert_equal 0, replies.size
  953. end
  954. MyObject = Struct.new :attribute1, :attribute2
  955. def test_serialized_attribute
  956. myobj = MyObject.new('value1', 'value2')
  957. topic = Topic.create("content" => myobj)
  958. Topic.serialize("content", MyObject)
  959. assert_equal(myobj, topic.content)
  960. end
  961. def test_nil_serialized_attribute_with_class_constraint
  962. myobj = MyObject.new('value1', 'value2')
  963. topic = Topic.new
  964. assert_nil topic.content
  965. end
  966. def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
  967. myobj = MyObject.new('value1', 'value2')
  968. topic = Topic.new(:content => myobj)
  969. assert topic.save
  970. Topic.serialize(:content, Hash)
  971. assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
  972. ensure
  973. Topic.serialize(:content)
  974. end
  975. def test_serialized_attribute_with_class_constraint
  976. settings = { "color" => "blue" }
  977. Topic.serialize(:content, Hash)
  978. topic = Topic.new(:content => settings)
  979. assert topic.save
  980. assert_equal(settings, Topic.find(topic.id).content)
  981. ensure
  982. Topic.serialize(:content)
  983. end
  984. def test_quote
  985. author_name = "\\ \001 ' \n \\n \""
  986. topic = Topic.create('author_name' => author_name)
  987. assert_equal author_name, Topic.find(topic.id).author_name
  988. end
  989. def test_quote_chars
  990. str = 'The Narrator'
  991. topic = Topic.create(:author_name => str)
  992. assert_equal str, topic.author_name
  993. assert_kind_of ActiveSupport::Multibyte::Chars, str.chars
  994. topic = Topic.find_by_author_name(str.chars)
  995. assert_kind_of Topic, topic
  996. assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
  997. end
  998. def test_class_level_destroy
  999. should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
  1000. Topic.find(1).replies << should_be_destroyed_reply
  1001. Topic.destroy(1)
  1002. assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
  1003. assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) }
  1004. end
  1005. def test_class_level_delete
  1006. should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
  1007. Topic.find(1).replies << should_be_destroyed_reply
  1008. Topic.delete(1)
  1009. assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
  1010. assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) }
  1011. end
  1012. def test_increment_attribute
  1013. assert_equal 1, topics(:first).replies_count
  1014. topics(:first).increment! :replies_count
  1015. assert_equal 2, topics(:first, :reload).replies_count
  1016. topics(:first).increment(:replies_count).increment!(:replies_count)
  1017. assert_equal 4, topics(:first, :reload).replies_count
  1018. end
  1019. def test_increment_nil_attribute
  1020. assert_nil topics(:first).parent_id
  1021. topics(:first).increment! :parent_id
  1022. assert_equal 1, topics(:first).parent_id
  1023. end
  1024. def test_decrement_attribute
  1025. topics(:first).increment(:replies_count).increment!(:replies_count)
  1026. assert_equal 3, topics(:first).replies_count
  1027. topics(:first).decrement!(:replies_count)
  1028. assert_equal 2, topics(:first, :reload).replies_count
  1029. topics(:first).decrement(:replies_count).decrement!(:replies_count)
  1030. assert_equal 0, topics(:first, :reload).replies_count
  1031. end
  1032. def test_toggle_attribute
  1033. assert !topics(:first).approved?
  1034. topics(:first).toggle!(:approved)
  1035. assert topics(:first).approved?
  1036. topic = topics(:first)
  1037. topic.toggle(:approved)
  1038. assert !topic.approved?
  1039. topic.reload
  1040. assert topic.approved?
  1041. end
  1042. def test_reload
  1043. t1 = Topic.find(1)
  1044. t2 = Topic.find(1)
  1045. t1.title = "something else"
  1046. t1.save
  1047. t2.reload
  1048. assert_equal t1.title, t2.title
  1049. end
  1050. def test_define_attr_method_with_value
  1051. k = Class.new( ActiveRecord::Base )
  1052. k.send(:define_attr_method, :table_name, "foo")
  1053. assert_equal "foo", k.table_name
  1054. end
  1055. def test_define_attr_method_with_block
  1056. k = Class.new( ActiveRecord::Base )
  1057. k.send(:define_attr_method, :primary_key) { "sys_" + original_primary_key }
  1058. assert_equal "sys_id", k.primary_key
  1059. end
  1060. def test_set_table_name_with_value
  1061. k = Class.new( ActiveRecord::Base )
  1062. k.table_name = "foo"
  1063. assert_equal "foo", k.table_name
  1064. k.set_table_name "bar"
  1065. assert_equal "bar", k.table_name
  1066. end
  1067. def test_set_table_name_with_block
  1068. k = Class.new( ActiveRecord::Base )
  1069. k.set_table_name { "ks" }
  1070. assert_equal "ks", k.table_name
  1071. end
  1072. def test_set_primary_key_with_value
  1073. k = Class.new( ActiveRecord::Base )
  1074. k.primary_key = "foo"
  1075. assert_equal "foo", k.primary_key
  1076. k.set_primary_key "bar"
  1077. assert_equal "bar", k.primary_key
  1078. end
  1079. def test_set_primary_key_with_block
  1080. k = Class.new( ActiveRecord::Base )
  1081. k.set_primary_key { "sys_" + original_primary_key }
  1082. assert_equal "sys_id", k.primary_key
  1083. end
  1084. def test_set_inheritance_column_with_value
  1085. k = Class.new( ActiveRecord::Base )
  1086. k.inheritance_column = "foo"
  1087. assert_equal "foo", k.inheritance_column
  1088. k.set_inheritance_column "bar"
  1089. assert_equal "bar", k.inheritance_column
  1090. end
  1091. def test_set_inheritance_column_with_block
  1092. k = Class.new( ActiveRecord::Base )
  1093. k.set_inheritance_column { original_inheritance_column + "_id" }
  1094. assert_equal "type_id", k.inheritance_column
  1095. end
  1096. def test_count_with_join
  1097. res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
  1098. res2 = nil
  1099. assert_deprecated 'count' do
  1100. res2 = Post.count("posts.#{QUOTED_TYPE} = 'Post'",
  1101. "LEFT JOIN comments ON posts.id=comments.post_id")
  1102. end
  1103. assert_equal res, res2
  1104. res3 = nil
  1105. assert_nothing_raised do
  1106. res3 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'",
  1107. :joins => "LEFT JOIN comments ON posts.id=comments.post_id")
  1108. end
  1109. assert_equal res, res3
  1110. res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
  1111. res5 = nil
  1112. assert_nothing_raised do
  1113. res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
  1114. :joins => "p, comments co",
  1115. :select => "p.id")
  1116. end
  1117. assert_equal res4, res5
  1118. unless current_adapter?(:SQLite2Adapter, :DeprecatedSQLiteAdapter)
  1119. res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
  1120. res7 = nil
  1121. assert_nothing_raised do
  1122. res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
  1123. :joins => "p, comments co",
  1124. :select => "p.id",
  1125. :distinct => true)
  1126. end
  1127. assert_equal res6, res7
  1128. end
  1129. end
  1130. def test_clear_association_cache_stored
  1131. firm = Firm.find(1)
  1132. assert_kind_of Firm, firm
  1133. firm.clear_association_cache
  1134. assert_equal Firm.find(1).clients.collect{ |x| x.name }.sort, firm.clients.collect{ |x| x.name }.sort
  1135. end
  1136. def test_clear_association_cache_new_record
  1137. firm = Firm.new
  1138. client_stored = Client.find(3)
  1139. client_new = Client.new
  1140. client_new.name = "The Joneses"
  1141. clients = [ client_stored, client_new ]
  1142. firm.clients << clients
  1143. assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
  1144. firm.clear_association_cache
  1145. assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
  1146. end
  1147. def test_interpolate_sql
  1148. assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo@bar') }
  1149. assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar) baz') }
  1150. assert_nothing_raised { Category.new.send(:interpolate_sql, 'foo bar} baz') }
  1151. end
  1152. def test_scoped_find_conditions
  1153. scoped_developers = Developer.with_scope(:find => { :conditions => 'salary > 90000' }) do
  1154. Developer.find(:all, :conditions => 'id < 5')
  1155. end
  1156. assert !scoped_developers.include?(developers(:david)) # David's salary is less than 90,000
  1157. assert_equal 3, scoped_developers.size
  1158. end
  1159. def test_scoped_find_limit_offset
  1160. scoped_developers = Developer.with_scope(:find => { :limit => 3, :offset => 2 }) do
  1161. Developer.find(:all, :order => 'id')
  1162. end
  1163. assert !scoped_developers.include?(developers(:david))
  1164. assert !scoped_developers.include?(developers(:jamis))
  1165. assert_equal 3, scoped_developers.size
  1166. # Test without scoped find conditions to ensure we get the whole thing
  1167. developers = Developer.find(:all, :order => 'id')
  1168. assert_equal Developer.count, developers.size
  1169. end
  1170. def test_scoped_find_order
  1171. # Test order in scope
  1172. scoped_developers = Developer.with_scope(:find => { :limit => 1, :order => 'salary DESC' }) do
  1173. Developer.find(:all)
  1174. end
  1175. assert_equal 'Jamis', scoped_developers.first.name
  1176. assert scoped_developers.include?(developers(:jamis))
  1177. # Test scope without order and order in find
  1178. scoped_developers = Developer.with_scope(:find => { :limit => 1 }) do
  1179. Developer.find(:all, :order => 'salary DESC')
  1180. end
  1181. # Test scope order + find order, find has priority
  1182. scoped_developers = Developer.with_scope(:find => { :limit => 3, :order => 'id DESC' }) do
  1183. Developer.find(:all, :order => 'salary ASC')
  1184. end
  1185. assert scoped_developers.include?(developers(:poor_jamis))
  1186. assert scoped_developers.include?(developers(:david))
  1187. assert scoped_developers.include?(developers(:dev_10))
  1188. # Test without scoped find conditions to ensure we get the right thing
  1189. developers = Developer.find(:all, :order => 'id', :limit => 1)
  1190. assert scoped_developers.include?(developers(:david))
  1191. end
  1192. def test_scoped_find_limit_offset_including_has_many_association
  1193. topics = Topic.with_scope(:find => {:limit => 1, :offset => 1, :include => :replies}) do
  1194. Topic.find(:all, :order => "topics.id")
  1195. end
  1196. assert_equal 1, topics.size
  1197. assert_equal 2, topics.first.id
  1198. end
  1199. def test_scoped_find_order_including_has_many_association
  1200. developers = Developer.with_scope(:find => { :order => 'developers.salary DESC', :include => :projects }) do
  1201. Developer.find(:all)
  1202. end
  1203. assert developers.size >= 2
  1204. for i in 1...developers.size
  1205. assert developers[i-1].salary >= developers[i].salary
  1206. end
  1207. end
  1208. def test_abstract_class
  1209. assert !ActiveRecord::Base.abstract_class?
  1210. assert LoosePerson.abstract_class?
  1211. assert !LooseDescendant.abstract_class?
  1212. end
  1213. def test_base_class
  1214. assert_equal LoosePerson, LoosePerson.base_class
  1215. assert_equal LooseDescendant, LooseDescendant.base_class
  1216. assert_equal TightPerson, TightPerson.base_class
  1217. assert_equal TightPerson, TightDescendant.base_class
  1218. assert_equal Post, Post.base_class
  1219. assert_equal Post, SpecialPost.base_class
  1220. assert_equal Post, StiPost.base_class
  1221. assert_equal SubStiPost, SubStiPost.base_class
  1222. end
  1223. def test_descends_from_active_record
  1224. # Tries to call Object.abstract_class?
  1225. assert_raise(NoMethodError) do
  1226. ActiveRecord::Base.descends_from_active_record?
  1227. end
  1228. # Abstract subclass of AR::Base.
  1229. assert LoosePerson.descends_from_active_record?
  1230. # Concrete subclass of an abstract class.
  1231. assert LooseDescendant.descends_from_active_record?
  1232. # Concrete subclass of AR::Base.
  1233. assert TightPerson.descends_from_active_record?
  1234. # Concrete subclass of a concrete class but has no type column.
  1235. assert TightDescendant.descends_from_active_record?
  1236. # Concrete subclass of AR::Base.
  1237. assert Post.descends_from_active_record?
  1238. # Abstract subclass of a concrete class which has a type column.
  1239. # This is pathological, as you'll never have Sub < Abstract < Concrete.
  1240. assert !StiPost.descends_from_active_record?
  1241. # Concrete subclasses an abstract class which has a type column.
  1242. assert !SubStiPost.descends_from_active_record?
  1243. end
  1244. def test_find_on_abstract_base_class_doesnt_use_type_condition
  1245. old_class = LooseDescendant
  1246. Object.send :remove_const, :LooseDescendant
  1247. descendant = old_class.create!
  1248. assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
  1249. ensure
  1250. unless Object.const_defined?(:LooseDescendant)
  1251. Object.const_set :LooseDescendant, old_class
  1252. end
  1253. end
  1254. def test_assert_queries
  1255. query = lambda { ActiveRecord::Base.connection.execute 'select count(*) from developers' }
  1256. assert_queries(2) { 2.times { query.call } }
  1257. assert_queries 1, &query

Large files files are truncated, but you can click here to view the full file