مشکل به روز رسانی در Ecto

با درود خدمت دوستان محترم .

در آموزشی که برای به روز رسانی مثلا یک مطلب در دیتابیس دیده بودم . طرف اومده بود کل اطلاعات رو در فرم فراخوانی کرد و بعد اومد به صورت زیر ارسال کرد :

مثلا :

def edit_user(id, map_params) do
		get_user_by_id(id)
		|> UsersInfo.changeset(map_params)
		|> Repo.update
end

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

من می خوام یک الی دو فیلد از این رکورد مثلا پسورد مثلا نام کاربر رو تغییر بدم ولی می خوام این یک تغییر از changeset من بگذره و شرط هایی که مربوط به اون هست رو هم طی کنه ولی به صورت زیر پیشنهاد داده شده به کاربر در داکیومنت ecto

post = MyRepo.get!(Post, 42)
post = Ecto.Changeset.change post, title: "New title"
case MyRepo.update post do
  {:ok, struct}       -> # Updated with success
  {:error, changeset} -> # Something went wrong
end

https://hexdocs.pm/ecto/Ecto.Repo.html#c:update/2

در اینجا همیشه بخاطر این تابع Ecto.Changeset.change ولید هست و هیچ یک از شرط های changeset من چک نمی شه .

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

با تشکر

از

MyRepo.change!

استفاده کن

https://hexdocs.pm/ecto/Ecto.Repo.html#c:update!/2

! خطا بر میگردونه

1 پسندیده

درود سام عزیز . ًمن چک کردم ًRepo.change نداریم تو توابع :thinking:

الان یک ارور در این کد یعنی وقتی که من ! اضافه کردم به update می ده که به ولیدیشن مربوط به اون فیلد زیاد فکر نمی کنم ربطی داشته باشه

قطعه کد

	def edit_user(id, map_params) do
		user = get_user_by_id(id)
		user = Ecto.Changeset.change user , map_params
		case Repo.update!(user) do
		  {:ok, struct}       -> IO.puts "updated"
		  {:error, changeset} -> IO.puts "not updated"
		end
	end

نوع وارد کردن :

iex(19)> UsersInfoQuery.edit_user("2c409b05-99d0-4f73-8dfe-fc3df9aa7c73", %{group_acl: "unactived"})

کارشو انجام می ده و یک ارور مثلا

** (CaseClauseError) no case clause matching: %TrangellUsersService.Login.Db.UsersInfo{__meta__: #Ecto.Schema.Metadata<:loaded, "usersinfo">, country: "Australia", email: "[email protected]", full_name: "shahryar tavakkoli", group_acl: "unactived", id: "2c409b05-99d0-4f73-8dfe-fc3df9aa7c73", inserted_at: ~N[2018-03-27 08:13:33.380492], language: "fa", last_ip: "127.0.0.1", lastname: nil, login_actions: #Ecto.Association.NotLoaded<association :login_actions is not loaded>, name: nil, password: nil, password_hash: "$2b$12$KqSpLbLkFvl6jw9D1QDR/uTw/NZPb4pdOf3XgfJfnbv9.Qi/bS6ki", profile_actions: #Ecto.Association.NotLoaded<association :profile_actions is not loaded>, token_actions: #Ecto.Association.NotLoaded<association :token_actions is not loaded>, updated_at: ~N[2018-04-02 19:07:04.106254]}
    (trangell_users_service) lib/trangell_users_service/login/db/users_info_query.ex:62: TrangellUsersService.Login.Db.UsersInfoQuery.edit_user/2

هم می ده بدون ! هیچ اروری نمی ده کارشم می کنه

درمورد Ecto.Changeset.change user ببنید لطفا . همیشه شرط true بر می گردونه می گه درست در صورتی که در ولیدیشن درست نیست به صورت مثال ببنید

در چنج ست من اومدم چنین ولیدیشنی رو قرار دادم گفتم حتما باید از این لیست باشه

|> validate_inclusion(:group_acl, ["actived", "unactived", "blocked", "registered"])

به تصویر زیر نگاه کنید چه درست چه غلط بازم می گه ولید هست . اصلا شرط های خود چنج ست برای این فیلد رو نگاه نمی کنه

شما با http request تست کن تو ترمینال changeset تو دور میزنی

1 پسندیده

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

کد ویرایش :

	def edit_user(id, map_params) do
		user = get_user_by_id(id)
		user = Ecto.Changeset.change(user , map_params)
		case Repo.update(user) do
		  {:ok, struct}       -> IO.inspect struct
		  {:error, changeset} -> IO.inspect changeset
		end
	end

کد فراخوانی در روتر

      def forget_password(conn, %{"id" => id , "group_acl" => group_acl}) do
            forget_passwords = case UsersInfoQuery.edit_user(id, %{group_acl: group_acl}) do
                  {:ok, _} ->
                        conn    
                        |> put_status(200)
                        |> json(%{message: "Your login was successful."})
                  {:error, _} ->
                        conn
                        |> put_status(403)
                        |> json(%{error_code: "403"})
            end
            forget_passwords
      end

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

راستی من اون Repo.update رو هم با ! و هم بدون اون تست کردم

ببخشید سام عزیز وقتتو دارم می گیرم شرمنده

edit_user با !update همینو میداد ؟

1 پسندیده

شما موردی که فرمودید یعنی :

def edit_user(id, map_params) do
		user = get_user_by_id(id)
		user = Ecto.Changeset.change(user , map_params)
		case Repo.update!(user) do
		  {:ok, struct}       -> IO.inspect struct
		  {:error, changeset} -> IO.inspect changeset
		end
	end

به شرح زیر می باشد

من خدمت شما عرض کنم که در هر دو مورد جدول هر اطلاعاتی که موقع درخواست برایش ارسال شود را آبدیت می کند. چه غلط چه درست . ارور ها فکر کنم یکی باشه

user دوبار نمیشه assign کرد immutable هستش

1 پسندیده

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

	def edit_user(id, map_params) do
		user = get_user_by_id(id)
		users = Ecto.Changeset.change(user , map_params)
		case Repo.update(users) do
		  {:ok, struct}       -> IO.inspect struct
		  {:error, changeset} -> IO.inspect changeset
		end
	end

متاسفانه ارور تغییری نکرد . همون ارور هست .

کد داکیومنتش

post = MyRepo.get!(Post, 42)
post = Ecto.Changeset.change post, title: "New title"
case MyRepo.update post do
  {:ok, struct}       -> # Updated with success
  {:error, changeset} -> # Something went wrong
end

https://hexdocs.pm/ecto/Ecto.Repo.html#c:update/2

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

Code بگذار گیت بعد نگاه میکنم چرا خطا میده

1 پسندیده

ممنون سام عزیز . پیغام خصوصی کردم خدمت شما .

ممنونم :rose: