پشتیبانی از اعداد فارسی در ریلز

دوستان برای این که اعداد فارسی هنگام ثبت فرمی (که فیلد عددی داره) توسط ریلز پشتیبانی بشه، دنبال یه راهکار کلی می‌گردم. من هم با یه متد به صورت before_validation در مدل و هم با یه متد توی کنترل و با جایگزینی اعداد فارسی با انگلیسی تونستم این کار رو انجام بدم، ولی دنبال یه راه حل system-wide برای پشتیبانی اعداد فارسی هستم.

ممنون

به کلاس String اضافه کن اون متد رو

1 پسندیده

مسئله اینه که اون متد کی اجرا می‌شه. قاعدتا چنین متدی باید روی داده دریافتی از تمامی فیلدهای عددی کل اپلیکیشن اجرا بشه. امکان چنین کاری هست؟

می تونی کلاس String رو تغییر بدی که کلا عدد فارسی نمایش بده

مشکل نمایش نیست. موقع اجرای ولیدیشن‌های عددی، داده‌ی عددی‌ای که params تو خودش داره باید با کاراکترهای انگلیسی باشه تا هنگام ثبت فرم، ارور «عدد نیست» نده. یعنی params دریافتی بجای این حالت

{..., "product"=>{"price"=>"۱۲۳۴"},...}

باید این حالت رو داشته باشیم:

{..., "product"=>{"price"=>"1234"},...}

حالا می‌شه کاری کرد که مثلا قبل از اینکه هش params ساخته بشه، اعداد فارسی رو با معادل انگلیسیش جایگزین کرد؟ یا حتی راه دیگه‌ای هست؟ (مثلا شناسوندن کاراکترهای اعداد فارسی به عنوان «عدد» به ریلز یا …)

@arvinje میتونی از tr استفاده کنی.

persianNumber = '۸۷۴۶۵۴۳۸۷۵۶۴۳۸۷۶'
engNumber = persianNumber.tr('۰۱۲۳۴۵۶۷۸۹', '0123456789')
puts engNumber

ببخشید زیاد ویرایش می کنم. هنوز ترکیب فونت فارسی و انگلیسی رو درست نمی تونم انجام بدم :joy:

http://apidock.com/ruby/String/tr

مشکل من متد تبدیل دوتا به هم نیست. مسئله اینه که کجا این متد اجرا بشه تا همه‌ی اعداد دریافتی فارسی (در کل اپ) به انگلیسی تبدیل بشن. که مثل نمونه بالا توی params دریافتی اعداد فارسی اصلا وجود نداشته باشن. یعنی می‌خوام این تبدیل توی یه سطح پایین‌تری قبل از این که به کنترلر برسه انجام شده باشه.

@arvinje براي اينكه اين كارو توي كنترلر انجام بدي بايد كد رو توي ApplicationController.rb بنويسي چون همه كنترلرها وارث اين كنترلر هستن، در ضمن ميتوني با رعايت كنوانسيون هاي ريلز (Convention-over-Configuration) خودت يه ماژل درست كني و تو هرجا كه خواستي include كني.
اگر من جاي شما باشم براي model ها يه ماژل مينويسم و ماژل رو توي يه پوشه به اسم همون ماژل قرار ميدم. ميشه پارامترها رو به شكل يه آرايه به متد پاس داد و خود متد رو به صورت سمبل (symbol) به before_save

اگه خواستي ميتونم يه gist روي gihub برات بزارم كه ببيني و البته حتما راه هاي بهتري هم براي اين كار هست.

این کارو به این سادگی نمی‌شه انجام داد. اول اینکه اگه صفت عددی باشه، داده‌ی رشته‌ای اصلا ذخیره نمی‌شه که حتی بشه به صورت before_validation رقم‌ها رو جایگزین کرد. دوم هم اینکه callbackها نمی‌تونن پارامتر بگیرن.

تنها راه کلی‌ای که من به نظرم می‌رسه اینه که تمام صفت‌های موجود توی هش params توی کنترلر از نظر عددی بودن بررسی بشن و اگه عددی بودن با ارقام انگلیسی جایگزین بشن که توی این حالت هم چون ممکنه هش شامل هش‌های تودرتو و آرایه هم باشه پرفورمنس خوبی نخواهد داشت.

البته می‌شه یه سری متد جایگزین new و update توی مدل ساخت که با گرفتن params قبل از فراخوانی new و update واقعی تبدیل رو انجام بدن. با این حال باز هم کل هش باید پیمایش بشه.

@arvinje چرا روی before_save توی model کار نمی کنی؟ فکر می کنم بهتر باشه مگر اینکه یک دلیل خیلی خوب وجود داشته باشه. من این تست رو انجام دادم. یه نمونه برات پست می کنم

در هر صورت اگه صفت (توی جدول)از نوع integer (یا float) تعریف شده باشه، داده‌ی رشته‌ای اصلا نمیتونه بهش نسبت داده‌بشه. همچنین درنظر داشته باش که میخوایم صفت بتونه از هر نوع ولیدیشن عددی هم پشتیبانی کنه.

@arvinje مم… جالب شد! البته من نمیدونم که آیا صفت یعنی سمبل یا خیر؟ من داشتم به همین داستان ولیدیشن فکر می کردم، به هر حال باید بتونیم این کارو انجام بدیم، سعی می کنم یه نگاهی به locale و internationalization بندازم، اما به نظرم این کار چندان نشدنی نیست. اگر جامعه ریلز راه حل آماده ای نداشت بازم یه کاریش می کنیم.

@arvinje نظرت در مورد اینکه همه اعداد رو توی داتابیس به انگلیسی سیو کنی ولی در عین حال سیستم همه اعداد رو در veiw به فارسی نشون بده چیه؟؟؟

همه اعداد طبیعتا به حالت integer یا float ذخیره می‌شن که انگلیسی و فارسی نداره. برای خروجی فارسی هم میشه یه متد مثل t نوشت که تبدیل رو انجام بده (یا حتی t رو تغییر بدیم)
مشکل اصلی هنگام سابمیت کردن فرم هاست. مسئله اینه که کاربر میتونه توی فیلد اون صفت* توی view رقم فارسی وارد کنه که این حالت پیش میاد

که در این صورت activerecord مقدار اون صفت رو صفر درنظر میگیره چون عدد فارسی رو پشتیبانی نمی‌کنه. یعنی حتی اون عدد توی صفت عددی ذخیره نمیشه که بشه تغییرش داد. پس باید قبل از انتساب صفت تغییر ارقام فارسی به انگلیسی انجام بشه.

*منظورم از صفت همون attribute هستش

پس یک راه میتونه نوشتن یه متد برگشتی (recursive) تو یه ماژل باشه که کل هش رو پویش کنه و هرجا با رشته برخورد کرد تبدیلش کنه. بازم همون که خودت گفتی :smile:

1 پسندیده

یه نمونه ازین متد (با همون بازگشتی) رو پیاده سازی کردم.

فقط کافیه این فایل رو require کرد (توی initializers) و هرجا که فیلد عددی وجود داره، مثل زیر روی params فراخوانی کرد

def product_params
    params.require(:product).permit(:title, :price, :description).fix_numerals
end

باز اگه راهکار بهتری باشه بگین بررسی کنیم :wink:

1 پسندیده