<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>پست‌های انتشارات کارنامه</title>
        <link>https://virgool.io/karnameh/feed</link>
        <description>کارنامه ارائه‌دهنده خدمات تخصصی خودرو مانند کارشناسی، فروش سفارشی، آگهی‌گذاری و خرید اقساطی است. علاوه بر این، برای اطلاع از قیمت روز خودرو، تخمین قیمت خودرو کارکرده و کارشناسی موتورسیکلت نیز می‌توانید روی کارنامه حساب کنید.</description>
        <language>fa</language>
        <pubDate>2026-04-14 09:09:35</pubDate>
        <image>
            <url>https://files.virgool.io/upload/publication/exfn7i8wvy68/4oyaoq.jpg</url>
            <title>کارنامه</title>
            <link>https://virgool.io/karnameh</link>
        </image>

                    <item>
                <title>از رفع یک باگ تا Contributor شدن در Sentry</title>
                <link>https://virgool.io/karnameh/contribute-on-sentry-yqmwgfoz6sij</link>
                <description>sentry.ioچند ماهی از ورودم به کارنامه میگذشت و تقریبا هرروز که Sentry رو باز میکردم یک Exception اون بالا میدیدم، که هر دقیقه با اجرای تسک‌های Celery ما تکرار میشد! این Exception از داخل کدهای Sentry(SDK) بود و اعصاب بچه‌های تیم رو بهم ریخته بود، چون هر چقدر کانفیگ پروژرو تغییر میدادن تاثیری نداشت.داخل این نوشته میخوام توضیح بدم که چطور یک تغییر کوچیک داخل کدهای Sentry(SDK) باعث شد که من Contributor بشم و این Exception هم دیگه داخل داشبورد Sentry ندیدیم، پس همراه من باشید.مشکل: KeyError عجیب و غریبمشکل ما یک KeyError بود که بعد از اتمام اجرای یک تسک Celery رخ میداد و میدونیم این زمانی رخ میده که بخوایم به یک کلید درون دیکشنری پایتونی دسترسی پیدا کنیم، ولی اون کلید وجود نداره.اینجا بود که دیدم ابزاری که ما برای رفع خطاها استفاده میکردیم، خودش عامل این Exception بود.پیدا کردن ریشه‌ی مشکلاز اونجایی که خیلی آدم پیگیری هستم، دیدم که اینطوری نمیشه و شروع کردم به گشت و گذار داخل کدهای کتابخانه Sentry Python تا بتونم این مشکل رو حل کنم و حتی شاید بتونم Contributorهم بشم.با یکم وقت گذاشتن و خوندن کدها، متوجه شدم که Sentry(SDK) قبل از اجرا شدن تسک های Celery، یک سری Metadata ست میکنه، مثلا زمان شروع اجرای تسک و اطلاعات دیگه. و بعد از اون تسک اجرا میشد و تمام.اما چه تمام شدنی، تازه  اینجا بود که Sentry میخواست مانیتور کنه که تسک چقدر طول کشید که کامل بشه و دقیقا اینجا بود که اون Metadata رو پیدا نمیکرد و باعث میشد دیکشنری پایتونی ما کلیدی که انتظار داشت رو نداشته باشه و به KeyError میخورد. من خیلی سعی کردم که روی لوکالم بتونم دیباگ کنم که چرا این اتفاق میفته، ولی اینجا بود که این جمله همیشگی اتفاق افتاد:رو لوکال من داره کار میکنه :)اما واقعا اینطوری بود که من روی پروداکشن فقط این Exception رو میدیدم و هرکاری میکردم روی سیستم خودم هیچ خبری نبود. این مشکل میتونست به خاطر OS یا پکیج های دیگه ای که روی اون نصب بود باشه. اما من نه وقت و نه دسترسی لازم برای بررسی کردن این موارد رو داشتم.اما میتونستم یک کار ساده تر و موقتی برای رفع این مشکل انجام بدم، اون هم این بود که هرکجا که Sentry(SDK) اومده از این تیکه کد استفاده کردرو تغییر بدم:float(headers[&amp;quotsentry-monitor-start-timestamp-s&amp;quot])هممون میدونیم که با متود get میشه به کلید دیکشنری دسترسی پیدا کرد و اگر کلید وجود نداشت KeyError رخ نده. اما صبر کنید، اگر این کلید وجود نداشت، من باید چه مقدار پیش فرضی رو در نظر میگرفتم؟اینجا بود که گفتم اگر بخوام تغییری بدم و Contribute بکنم، باید تست های Sentry(SDK) کامل پَس بشن و نمیتونم همینجوری مقدار پیش فرض رو صفر یا مقدار دیگه ای در نظر بگیرم و ممکنه تست ها پَس نشن. به خاطر همین گفتم یک نگاهی هم به تست های این کتابخانه بندازم. خوشبختانه دیدم که اگر مقدار sentry-monitor-start-timestamp-s رو None در نظر بگیرم، تست ها به درستی پَس میشن!منطقی هم بود، چون مانیتور کردن اینکه زمان اجرای این تسک چقدر بوده مهم نبود(حداقل برای ما) و خود لاگ های Celery Beat هم این دیتا رو به ما میداد...در نهایت با بررسی کدهای کتابخانه پایتونی Sentry و نگاه کردن به تست های پروژشون، دیدم که میتونم خیلی راحت اون تیکه کد رو به این تغییر بدم و مشکلمون حل بشه:headers.get(&amp;quotsentry-monitor-start-timestamp-s&amp;quot)با استفاده از متود get از رخ دادن KeyError جلوگیری کردم و مقدار پیش فرض هم None در نظر گرفتم و چند خط از کدهای کتابخونرو همینجوری تغییر دادم.از باگ تا انتشاروقتی دیدم تونستم این مشکل رو حل کنم، گفتم چرا به عنوان Issue داخل گیت هاب مطرحش نکنم؟ اصلا شاید ما جایی داریم اشتباه میکنیم و توسعه دهنده های خود Sentry بیان و مارو راهنمایی کنن. که این کار رو انجام دادم و با صحبت هایی که با این تیم داشتم و لاگ‌هایی که در اختیارشون قرار دادم، مشکلی از سمت کانفیگ‌های مارو متوجه نشدن و به نظر همه چیز داخل کدهای ماهم درست بود و مشکلی رو پیدا نکردیم. پس در نهایت قبول کردند که این تغییرات در Sentry Python مرج بشه، چرا که حداقل از نظر Best Practice بهتر هم هست.Release: Sentry Python 2.11.0 releasedIssue: #3277Pull Request: #3278نتیجه گیریاین تجربه به من نشون داد که مشکلات به ظاهر کوچیک، فرصتی برای یادگیری و رشد هستند. با بررسی کدهای Sentry(SDK) و مشارکت در پروژه اوپن سورس، نه تنها مشکل تیم رو حل کردم، بلکه به جامعه توسعه دهندگان هم کمک کردم تا از بروز همان خطا جلوگیری کنند.</description>
                <category>کارنامه</category>
                <author>Mohsen Khodabakhshi</author>
                <pubDate>Sun, 11 May 2025 13:52:47 +0330</pubDate>
            </item>
                    <item>
                <title>روشی هوشمندانه برای ساخت فرم‌های پویا در React</title>
                <link>https://virgool.io/karnameh/%D8%B1%D9%88%D8%B4%DB%8C-%D9%87%D9%88%D8%B4%D9%85%D9%86%D8%AF%D8%A7%D9%86%D9%87-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%B3%D8%A7%D8%AE%D8%AA-%D9%81%D8%B1%D9%85-%D9%87%D8%A7%DB%8C-%D9%BE%D9%88%DB%8C%D8%A7-%D8%AF%D8%B1-react-f4zdxspufpos</link>
                <description>بسیاری از شرکت‌ها و سازمان‌ها برای جمع‌آوری اطلاعات کاربران یا مدیریت داده‌ها، نیاز دارند فرم‌های متنوعی طراحی کنند. اگر این فرم‌ها به‌صورت استاتیک طراحی شوند، یعنی به‌صورت دستی ساخته شده و ثابت باقی بمانند، نگهداری و توسعه آن‌ها در آینده دردسرساز خواهد بود. این مشکل به‌ویژه در وب‌سایت‌هایی که با خودرو سروکار دارند بیشتر دیده می‌شود، چراکه خودروها مدل‌ها و ویژگی‌های مختلفی دارند. بنابراین، فرم‌ها باید پویا بوده و بتوانند خود را با این ویژگی‌ها تطبیق دهند.ما در کارنامه با همین چالش مواجه بودیم. به سیستمی نیاز داشتیم که بتواند فرم‌های مرتبط با انواع خودروها را در سمت فرانت‌اند به‌صورت خودکار ایجاد کند. از آنجا که هر خودرو ویژگی‌های خاص خودش را دارد، باید فرمی متناسب با آن نیز تولید شود. به‌جای طراحی فرم جداگانه برای هر مدل خودرو، به‌دنبال راه‌حلی خودکار و مقیاس‌پذیر بودیم.راه‌حل ما استفاده از JSON Schema Form در React بود. این روش به ما اجازه می‌دهد با استفاده از یک JSON Schema، فرم‌های پویا تولید کنیم. دیگر نیازی نیست برای هر خودرو یک فرم جداگانه طراحی شود. فقط کافی‌ست برای هر خودرو یک JSON داشته باشیم تا خودش فرم مناسب را بسازد.در واقع JSON Schema  یک استاندارد برای توصیف ساختار داده‌هاست که مشخص می‌کند هر فیلد در فرم باید چه نوع داده‌ای دریافت کند، چه محدودیت‌هایی داشته باشد و چگونه نمایش داده شود. با کمک کتابخانه‌هایی مانند react-jsonschema-form، این اسکیما مستقیماً به یک فرم قابل استفاده در React تبدیل می‌شود.در این مقاله، قرار است با JSON Schema Form آشنا شویم، نحوه پیاده‌سازی آن در پروژه‌های React را بررسی کنیم و ببینیم چرا این روش در برخی سناریوها می‌تواند راه‌حلی کارآمد و هوشمندانه باشد.ساختار JSON Schema چیه؟ساختار JSON Schema کمک میکنه داده های ساختاریافته ای که تو JSON داریم رو تعریف، توصیف و اعتبارسنجی کنیم. به زبون ساده، مشخص میکنه که داده ها چه شکلی باید باشن، چه محدودیت هایی داشته باشن و چطور به هم مرتبط باشن. این استاندارد تضمین میکنه که اطلاعات ورودی (چه از طرف کاربرا، چه از سیستم های دیگه) دقیقاً مطابق انتظارات ما باشه و جلوی ورود داده های نامعتبر رو میگیره.یه مثال ساده بزنیم. فرض کن میخوای مشخصات یه ماشین رو تو سیستم ذخیره کنی. میتونی این کارو با یه JSON Schema مثل زیر انجام بدی:{
    &#039;type&#039;: &#039;object&#039;,
    &#039;properties&#039;: {
        &#039;brand&#039;: {
            &#039;type&#039;: &#039;string&#039;,
            &#039;description&#039;: &#039;نام سازنده خودرو&#039;
        },
        &#039;model&#039;: {
            &#039;type&#039;: &#039;string&#039;,
            &#039;description&#039;: &#039;مدل خودرو&#039;
        },
        &#039;year&#039;: {
            &#039;type&#039;: &#039;integer&#039;,
            &#039;description&#039;: &#039;سال تولید&#039;,
            &#039;minimum&#039;: 1900,
            &#039;maximum&#039;: 2024
        },
        &#039;color&#039;: {
            &#039;type&#039;: &#039;string&#039;,
            &#039;description&#039;: &#039;رنگ خودرو&#039;,
            &#039;enum&#039;: [&#039;قرمز&#039;, &#039;آبی&#039;, &#039;سفید&#039;, &#039;مشکی&#039;]
        }
    },
    &#039;required&#039;: [&#039;brand&#039;, &#039;model&#039;, &#039;year&#039;]
}توضیح این JSON Schema:مقدار type: object مشخص می‌کند که این اسکیما یک شیء (Object) را توصیف می‌کند.کلید properties ویژگی‌های مختلف آن شیء (در اینجا، ویژگی‌های ماشین) را تعریف می‌کند.کلید های brand, model, year, color: مشخصات مختلف ماشین رو تعیین میکنن.مقدار type نوع هر ویژگی را مشخص می‌کند (مثل عدد، رشته و …).مقدار description توضیح مختصری از هر ویژگی ارائه می‌دهد که اجباری نیست.مقادیر minimum و maximum برای ویژگی year، بازه مجاز را تعیین می‌کنند.مقادیر enum برای ویژگی color، رنگ‌های مجاز را لیست می‌کنند.مقادیر required تعیین می‌کنند که کدام فیلدها حتماً باید مقدار داشته باشند.این JSON Schema یک ساختار مشخص برای اطلاعات ماشین ایجاد می‌کند که می‌توان از آن برای اعتبارسنجی ورودی‌ها، ساخت فرم‌های داینامیک و حتی مستندسازی API استفاده کرد. برای مثال، JSON زیر با JSON Schema بالا مطابقت دارد:{
    &#039;brand&#039;: &#039;BMW&#039;,
    &#039;model&#039;: &#039;7 series&#039;,
    &#039;year&#039;: 2020,
    &#039;color&#039;: &#039;قرمز&#039;
}اما JSON زیر مطابقت نداره چون که مقدار &quot;نوک مدادی&quot; توی enum اسکیما وجود نداره:{
    &#039;brand&#039;: &#039;MW&#039;,
    &#039;model&#039;: &#039;7 series&#039;,
    &#039;year&#039;: 2020,
    &#039;color&#039;: &#039;نوک مدادی&#039;
}برای مطالعه ی بیشتر JSON Schema این لینک رو مطالعه کنید.استفاده از JSON Schema Form در React:حالا که با JSON Schema آشنا شدیم، می‌توانیم از آن برای ساخت فرم‌های داینامیک در React استفاده کنیم. یکی از محبوب‌ترین کتابخانه‌هایی که این کار را انجام می‌دهد، @rjsf/core (که نسخه قبلی‌اش به نام react-jsonschema-form شناخته می‌شد) است.برای استفاده از این کتابخانه، کافی است که کامپوننت Form را از این کتابخانه وارد کرده و JSON Schema خود را به آن پاس بدهیمimport React from &#039;react&#039;;
import Form from &#039;@rjsf/core&#039;;

const schema = {
    // ... JSON Schema of previous example
};

const MyForm = () =&gt; {
    const  changeHandler= ({ formData }) =&gt; {
        console.log(&#039;Data submitted: &#039;, formData);
        // do anything you want with data
    };

    return (
        &lt;Form schema={schema} ={changeHandler} /&gt;
    );
};

export default MyForm;توضیح کد:کامپوننت Form از @rjsf/core مسئول تبدیل JSON Schema به یک فرم React است.مقدار schema: در اینجا JSON Schema مورد نظر را به کامپوننت Form می‌دهیم.تابع changeHandler: یک تابع ایجاد می‌کنیم که هنگام ارسال فرم (submit) اجرا می‌شود و داده‌های ورودی را پردازش می‌کند.با این روش، فرم‌های React به‌صورت خودکار ساخته می‌شوند و نیازی نیست برای هر مدل خودرو یک فرم جداگانه طراحی کنیم. کامپوننت @rjsf/core خودش ورودی‌های مناسب (مانند input، select، textarea و …) را بر اساس نوع داده‌های JSON Schema ایجاد می‌کند و همچنین اعتبارسنجی‌ها (مثل minimum، maximum، enum و …) را به‌طور خودکار اعمال می‌کند.نتیجه‌ی مثال بالا رو توی تصویر میتونید ببینید که توی  صفحه ی دمو وبسایت اصلی این کتابخانه ساخته شده:سفارشی‌سازی فرم‌هااما این فقط آغاز ماجراست و این ابزار خیلی فراتر از ساخت یک فرم ساده است! شما می‌توانید در این پکیج، فرم‌ها و ویجت‌های سفارشی بسازید، استایل‌ها را تغییر دهید و حتی رفتار فرم را با استفاده از UISchema کنترل کنید. برای مثال، در مرحله “وضعیت بدنه” در صفحه‌ی ثبت آگهی کارنامه، تمام فرم با همین روش، یعنی JSON Schema Form، مدیریت می‌شود که تصویر آن را می‌توانید در زیر مشاهده کنید. برای آشنایی بیشتر با پکیج JSON Schema Form، این لینک را مطالعه کنید.جمع‌بندیاستفاده از JSON Schema Form در React یک راهکار فوق‌العاده برای ساخت فرم‌های داینامیک و مقیاس‌پذیر است. به‌جای اینکه برای هر فرم به‌صورت دستی کامپوننت‌های مختلف طراحی کنیم، می‌توانیم از JSON Schema برای تعریف ساختار فرم و از کتابخانه‌هایی مثل @rjsf/core برای تولید خودکار آن استفاده کنیم. اگر دنبال یک روش بهینه برای ساخت فرم‌های پویا در پروژه‌های React هستید، JSON Schema Form می‌تواند انتخاب عالی‌ای باشد.</description>
                <category>کارنامه</category>
                <author>مهران صادقی</author>
                <pubDate>Sun, 02 Mar 2025 15:24:24 +0330</pubDate>
            </item>
            </channel>
</rss>