test: cover OrmNestedAttributesTest and teardown
This commit is contained in:
1 parent
b8cca00f06
commit
6b2d8f51a2
1 file changed
+166
@@ -0,0 +1,166 @@
|
||||
require 'minitest/autorun'
|
||||
require 'prism'
|
||||
require 'tmpdir'
|
||||
|
||||
class OrmNestedAttributesTest < Minitest::Test
|
||||
def setup
|
||||
@dir = Dir.mktmpdir('prism-nested-attrs-store')
|
||||
@store = Prism::Orm::Store.new(File.join(@dir, 'test.pstore'))
|
||||
@store.create_table(:posts, %w[id title])
|
||||
@store.create_table(:comments, %w[id body post_id])
|
||||
@store.create_table(:accounts, %w[id owner_id plan])
|
||||
@store.create_table(:users, %w[id name])
|
||||
|
||||
post_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :posts
|
||||
has_many :comments, class_name: 'Comment', foreign_key: 'post_id', dependent: :destroy
|
||||
accepts_nested_attributes_for :comments, allow_destroy: true, reject_if: :all_blank, limit: 3
|
||||
end
|
||||
comment_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :comments
|
||||
belongs_to :post, class_name: 'Post', foreign_key: 'post_id'
|
||||
validates :body, presence: true, length: { minimum: 2 }
|
||||
end
|
||||
user_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :users
|
||||
has_one :account, class_name: 'Account', foreign_key: 'owner_id'
|
||||
accepts_nested_attributes_for :account
|
||||
end
|
||||
account_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :accounts
|
||||
belongs_to :owner, class_name: 'User', foreign_key: 'owner_id'
|
||||
validates :plan, presence: true
|
||||
end
|
||||
|
||||
[post_class, comment_class, user_class, account_class].each { |klass| klass.store = @store }
|
||||
Object.const_set(:Post, post_class)
|
||||
Object.const_set(:Comment, comment_class)
|
||||
Object.const_set(:User, user_class)
|
||||
Object.const_set(:Account, account_class)
|
||||
end
|
||||
|
||||
def teardown
|
||||
FileUtils.remove_entry(@dir)
|
||||
%i[Post Comment User Account].each { |name| Object.send(:remove_const, name) if Object.const_defined?(name) }
|
||||
end
|
||||
|
||||
def test_builds_and_saves_new_children_of_a_new_parent
|
||||
post = Post.create!(
|
||||
title: 'hello',
|
||||
comments_attributes: [{ body: 'first' }, { body: 'second' }]
|
||||
)
|
||||
|
||||
assert_equal 2, Comment.where(post_id: post.id).count
|
||||
bodies = Comment.where(post_id: post.id).map(&:body).sort
|
||||
assert_equal %w[first second], bodies
|
||||
end
|
||||
|
||||
def test_accepts_indexed_hash_form_like_a_rails_form_builder
|
||||
post = Post.create!(
|
||||
title: 'hello',
|
||||
comments_attributes: { '0' => { body: 'first' }, '1' => { body: 'second' } }
|
||||
)
|
||||
|
||||
assert_equal 2, Comment.where(post_id: post.id).count
|
||||
end
|
||||
|
||||
def test_updates_an_existing_child_by_id
|
||||
post = Post.create!(title: 'hello')
|
||||
comment = Comment.create!(body: 'original', post_id: post.id)
|
||||
|
||||
post.update!(comments_attributes: [{ id: comment.id, body: 'edited' }])
|
||||
|
||||
assert_equal 'edited', comment.reload.body
|
||||
end
|
||||
|
||||
def test_allow_destroy_removes_the_child
|
||||
post = Post.create!(title: 'hello')
|
||||
comment = Comment.create!(body: 'doomed', post_id: post.id)
|
||||
|
||||
post.update!(comments_attributes: [{ id: comment.id, _destroy: '1' }])
|
||||
|
||||
assert_nil Comment.store.find(Comment.table_name, comment.id)
|
||||
end
|
||||
|
||||
def test_destroy_flag_is_ignored_without_allow_destroy
|
||||
no_destroy_post_class = Class.new(Prism::Orm::Model) do
|
||||
table_name :posts
|
||||
has_many :comments, class_name: 'Comment', foreign_key: 'post_id'
|
||||
accepts_nested_attributes_for :comments
|
||||
end
|
||||
no_destroy_post_class.store = @store
|
||||
post = no_destroy_post_class.create!(title: 'hello')
|
||||
comment = Comment.create!(body: 'kept', post_id: post.id)
|
||||
|
||||
post.update!(comments_attributes: [{ id: comment.id, _destroy: '1', body: 'still here' }])
|
||||
|
||||
refute_nil Comment.store.find(Comment.table_name, comment.id)
|
||||
assert_equal 'still here', comment.reload.body
|
||||
end
|
||||
|
||||
def test_reject_if_all_blank_skips_empty_new_records
|
||||
post = Post.create!(title: 'hello', comments_attributes: [{ body: '' }, { body: 'real' }])
|
||||
|
||||
assert_equal 1, Comment.where(post_id: post.id).count
|
||||
assert_equal 'real', Comment.where(post_id: post.id).first.body
|
||||
end
|
||||
|
||||
def test_limit_raises_when_exceeded
|
||||
assert_raises(Prism::Orm::NestedAttributes::TooManyRecords) do
|
||||
Post.create!(title: 'hello', comments_attributes: [{ body: 'a' }, { body: 'b' }, { body: 'c' }, { body: 'd' }])
|
||||
end
|
||||
end
|
||||
|
||||
def test_invalid_nested_record_blocks_the_whole_save_and_reports_errors
|
||||
post = Post.new(title: 'hello', comments_attributes: [{ body: 'good enough' }, { body: 'x' }])
|
||||
|
||||
refute post.save
|
||||
assert post.new_record?
|
||||
assert post.errors.key?(:comments)
|
||||
assert_equal 0, Comment.count
|
||||
end
|
||||
|
||||
def test_id_pointing_at_another_parents_child_is_rejected_not_hijacked
|
||||
post_a = Post.create!(title: 'a')
|
||||
post_b = Post.create!(title: 'b')
|
||||
foreign_comment = Comment.create!(body: 'belongs to a', post_id: post_a.id)
|
||||
|
||||
refute post_b.update(comments_attributes: [{ id: foreign_comment.id, body: 'hijacked' }])
|
||||
assert_equal 'belongs to a', foreign_comment.reload.body
|
||||
assert_equal post_a.id, foreign_comment.reload.post_id
|
||||
end
|
||||
|
||||
def test_id_on_a_brand_new_parent_is_rejected
|
||||
post = Post.new(title: 'hello', comments_attributes: [{ id: 999, body: 'ghost' }])
|
||||
|
||||
refute post.save
|
||||
assert post.errors.key?(:comments)
|
||||
end
|
||||
|
||||
def test_has_one_nested_attributes_builds_the_single_record
|
||||
user = User.create!(name: 'ada', account_attributes: { plan: 'pro' })
|
||||
|
||||
account = Account.find_by(owner_id: user.id)
|
||||
refute_nil account
|
||||
assert_equal 'pro', account.plan
|
||||
end
|
||||
|
||||
def test_has_one_nested_attributes_updates_the_existing_record
|
||||
user = User.create!(name: 'ada')
|
||||
account = Account.create!(plan: 'free', owner_id: user.id)
|
||||
|
||||
user.update!(account_attributes: { id: account.id, plan: 'pro' })
|
||||
|
||||
assert_equal 'pro', account.reload.plan
|
||||
end
|
||||
|
||||
def test_does_not_support_associations_other_than_has_many_or_has_one
|
||||
assert_raises(ArgumentError) do
|
||||
Class.new(Prism::Orm::Model) do
|
||||
table_name :comments
|
||||
belongs_to :post, class_name: 'Post', foreign_key: 'post_id'
|
||||
accepts_nested_attributes_for :post
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user