حذف موارد رلیشن شده در Ecto در الکسیر و نوع درخواست در فونیکس

با درود خدمت عزیزان .

قبلا در مورد رلیشن زدن تو در تو در الکسیر پستی زدم گفتم اگر دوست داشتید ببنید البته به زودی باید خودمم در پروژم اون رو اعمال کنم

این پست نیز تقریبا کمی مرتبط هست گفتم خدمت شما عزیزان نیز این سوال مطرح کنم تا به صرت کامل یک داکیومنت در انجمن بمونه

فرض بفرمایید ما یک مجموعه داریم که این مجموعه داخل خودش ۱۰۰ مطلب داره . حال می خواهیم سه گزینه برای کاربر فراهم کنیم .

۱. با حذف اون مجموعه تمام پست های زیر مجموعه اون هم پاک بشه
۲. فقط مجموعه پاک بشه و پست ها باقی بمونند
۳. فقط یکی از پست های اون مجموعه پاک بشه

نکته من هنوز کد هارو تست نکردم فقط دلیت خالی رو تست کردم چون رلیشن بود بهم ارور داد

بهترین پستی که پیدا کردم به شرح زیر بود

در اینجا برای دو گزینه اول اومدن دو راه رو در چند مطلب اول پیشنهاد دادن


۱. بر اساس اکشن دلیت دو جدول پاک بشه به عنوان مثال

بجای

add :cms_post_category_id, references(:cms_post_category, on_delete: :nothing, type: :uuid)

بیایند به این صورت رفتار کنند

add :cms_post_category_id, references(:cms_post_category, on_delete: :delete_all, type: :uuid)

به این صورت اگر در جدول مادر که جدول فعلی به اون رفرنس شده اونجا تصمیم گرفته بشه حذف بشه کل زیر مجموعه های رلیشن شده نیز فکر می کنم حذف بشه .

تا اینجا اگر در مورد گزینه یک ۱ نظری دارید لطفا بفرمایید و همینطور برام جالب هست اگر این کد کار بکنه ولی جداول ما زیاد باشند در کل جدول رلیشن شده تعداد زیادی رکورد داشته باشه چه بلایی روی سر دیتابیس می یاد ؟ ممکن هست فیلد بشه این درخواست اگر بله راه حل جایگزین چیست


۲. بر اساس بدون واکنش

در راه حل دیگری که یک فرد دیگری داد این بود که بیایند به صورت زیر عمل کنند

post
|> Ecto.Changeset.change
|> Ecto.Changeset.no_assoc_constraint(:comments)
|> Repo.delete

اینطور که مشخصه از کد و بنده هنوز تاکید می کنم تست نکردم به درخواست مورد نظر می گه بی خیال باشه بزار طرف حذف بشه :grin: . مثلا مجموعه حذف بشه ولی مطالبش خیر .

آیا برای گزینه دوم نظری دارید ؟ آیا این راه منطقی می باشد ؟


و در آخرین مطلب هم فکر می کنم یعنی گزینه ۳ که به صورت عادی انجام باید بشود چون در حقیقت این جدول زیر مجموعه می باشد و رلیشنی با جایی ندارد جز مادرش که مجموعه می باشد

که فکر کنم باید به صورت زیر انجام بشه

post = Repo.get!(Post, id)
    |> Post.changeset

    case Repo.delete(post) do

سوال در مورد درخواست ارسالی

برای من یک سوالی نیز در این وسط ایجاد می شود که جدای سوالات بالا هست ولی مرتبط آیا نیاز هست ما از طرف کاربر برای دلیت رکواست DELETE بگیریم مثلا چه فرقی با POST می کند ؟

https://hexdocs.pm/phoenix/Phoenix.Router.html#resources/4-singleton-resources

با تشکر از دوستان می خواستم جوری این پست کامل باشه از نظر سوالات و همینطور پاسخی که شما عزیزان می دید تا برای افرادی که بعدا می خواند الکسیر رو شروع کنند مخصوصا در زمینه دیتابیس و Ecto این پست براشون بسیار کامل و پاسخگو باشه

اول که چرا حتما باید delete کنی میتونی soft delete کنی
دوم اگه باید delete کنی اگه association مثله comment با پاک شدن پست به خودی خود بی معنا میشه و به اصطلاح یتیم orphan میشه باید پاک شه همراهه post
بله DELETE راه درستشه از نظره REST

1 پسندیده

درود سام عزیز امید وارم حالت خوب باشه و همچنین در سلامتی باشید .

من منظور شما رو از soft delete متوجه نشدم می شه بیشتر توضیح بدید ؟ یا قطعه کدی در این زمینه دارید ؟ چون رلیشن شده در پست اول هم خدمتتون توضیح دادم ارور می داده به همین ترتیب مجبور به جستجو شدم تا کدی پیدا کنم که چنین موردی رو انجام بده البته هنوز تست نزدمش

البته از نظر نظرات صحبت شما کاملا صحیح هست ولی فکر کنید مثلا ۱۰۰ مقاله ارسال شده که زیر مجموعه مجموعه ورزشی بوده با این تفاوت فکر می کنم که حذف نشه بهتره

1 پسندیده

soft delete یعنی در حقیقت delete نکنی فقط یک فیلد مثله is_deleted ست بکنی به true

1 پسندیده

ممنون سام عزیز.

بله بسیار نظر خوبی هست بهش فکر نکرده بودم البته هر رکوردم یک status داره برای فعال یا غیر فعال سازیش . سام عزیز سوال درخواستم یکمی بیشتر ازتون بپرسم

مثلا برای ساخت در دیتابیس put و در حذف از delete با اینکه من جستجو کردم امروز ولی دقیق دقیق متوجه نشدم چقدر با هم تفاوت دارند آیا در delete و رکوست مورد نظر تفاوتی ایجاد می کند ؟مثلا از نظر امنیتی یا چیزی ؟

درخواستی مثل PATCH که متوجه نشدم فکر کنم برای به روز رسانی استفاده می شه :thinking:

GET برای خواندن
PUT برای به روز رسانی
POST برای ساختن
DELETE برای پاک کردن

PATCH جدیدتر برای برای بروزرسانی برخلاف Put که کل داده نیاز داره patch فقط قسمت update شده رو میگیره

1 پسندیده

سام عزیز اون حذف مجموعه با کل پست رو انجام دادم که یک بخشی از یادگیریم بود ولی متاسفانه نمی تونم مجموعه رو پاک کنم تا پست هام یتیم بمونند

کد بنده

def delete_post_category(id) do
		# it needs to test wehen the clinet imports data on the cms_post.
		category = get_category_by_id(id)
		|> Ecto.Changeset.change
		|> Ecto.Changeset.no_assoc_constraint(:cms_post)

		case Repo.delete(category) do
			{:ok, _} -> {:ok}
			{:error, changeset} -> {:error, changeset}
		end
	end

اتفاقا کد هم ارور نمی ده و به تصویر زیر نگاه کنید درخواست هم می ره ولی حذفش نمی تونه بکنه. (اگر حذف نتونه بکنه تنظیم کردم ارور بده )

این کدم در حقیقت یتیم نمی کنه بلکه تا زمانی که تمام پست های مجموعه پاک نشه مجموعه رو پاک نمی کنه ولی اگر پستی زیرش نبود پاک می کنه. چطور یتیم سازی رو انجام بدم که این مورد رو هم یاد بگیرم.

delete خالی فقط rollback میکنه از !delete استفاده کن اگه میخای ارور ببینی

مشکلو من متوجه نمیشم چی هستش اینجا برات اگه constraint بگذاری نمیزاره داده ها یتیم بشن اگه نگذاری اجازه میده
هدفه اصلی چیه یتیم شدن برات مهم نیست ؟ در این صورت از constraint استفاده نکن

1 پسندیده

https://www.postgresql.org/docs/9.4/static/ddl-constraints.html

قسمته foreign key
cascade delete ببین

ON DELETE CASCADE یک constraint که داده های مربوط با پاک شدن داده سرپرست پاک میکنه

1 پسندیده

سام عزیز من برای این پست و پیشرفتنش با کمک شما , مجددا تشکر کنم شاید ۲۰ بار به مشکل خوردم در موارد مختلف حذف و مراجعه کردم به این پست واقعا ممنونم

1 پسندیده