از چه ساختاری برای سرور مبتنی بر‪ Ruby on Rails ‬استفاده کنیم؟

Ali Sepehri
salamcinema
Published in
3 min readDec 8, 2016

تو این مقاله کاری به اینکه چرا از‪ Ruby on Rails ‬استفاده کنیم یا نکنیم ندارم و فقط می‌خوام ساختاری رو که تو برنامه‌م ترجیح میدم داشته باشم رو بنویسم و خیلی خوشحال میشم که پیشنهادهای شما رو هم در این رابطه بدونم.

همون طور که میدونیم‪ RoR ‬ازمعماری‪ MVC ‬استفاده می‌کنه و خیلی شمارو به سمتی هُل میده که شما هم از این معماری خارج نشین که مزایای خیلی خوبی داره: به راحتی می‌تونین کد بقیه رو بفهمین و دباگ کنین، تو این حالت میشه‪ CLI ‬های خیلی خوبه براش نوشت، تو کار تمیمی خیلی نگران نیستین که سایر هم‌تیمی‌ها از معماری خارج بشن و‪ …

راستش من همیشه از اینکه این ساختار رو داشته باشم ناراضی بودم و همیشه خلاء یک لایه‌ی دیگه‌رو احساس می‌کردم و‪ Best Practice ‬هایی که موجود بودن هم پیشنهاد می‌کنن که شما اکثر توابع خودتون رو تو‪ Model ‬ها بنویسین و اون‌هارو چاق کنین و‪ Controller ‬های لاغری داشته باشین. اما مشکلی که من داشتم این بود که یک سری منطق‌های هستن که برای اجرا شدن نیاز دارن از چند مُدل استفاده کنن و توابع نمی‌تونن داخل یک مُدل باشن، پس یک لایه‌ی دیگری رو نیاز داشتم که به اصطلاح‪ Business Logic ‬خودم رو تو اون بنویسم. پس یک لایه به نام‪ services ‬به کد من اضافه شد.

افزودن لایه‪ Service ‬به معماری‪ MVC ‬

برای پیاده‌سازی لایه‪ Service ‬از ساختارهای مختلفی میشه استفاده کرد. من یه مدت از‪ wisper ‬استفاده می‌کردم. اما یه سری مشکلات اساسی داشت که باعث شد کاملا کنارش بذارم و حتی الان هم جاهایی که می‌بینم از این ساختار استفاده شده‪ refactor ‬می‌کنم.

تو نوشتن‪ API ‬یکی از چیزهایی که من آرزو داشتم داشته باشم اعتبارسنجی پارامترهایی ورودی بود. میدیدم بچه‌ها از‪ grape ‬برای نوشتن‪ API ‬استفاده می‌کنن و این ويژگی تو این جِم هست و چون من از این جِم خوشم نمیومد، سعی داشتم که این نیازم رو جور دیگه‌ای برطرف کنم. جم‪ grape ‬کار اعتبارسنجی رو تو لایه‌ی‪ view ‬انجام میده و البته مزیایا خودش رو داره، اما من از چاق شدن کنترولرها شاکی بودم و دنبال جایگزین برای این جِم بودم تا اینکه‪ active interaction ‬رو دیدم.

اگر بخوام نقاط قوت این جِم رو بگم: ۱.اعتبارسنجی پارامتر‌های ارسال شده ۲.جلوگیری از داشتن کنترولرهای چاق(کد زیاد) ۳. افزایش قابلیت استفاده مجدد سرویس‌ها ۴. مدیریت مناسب خطاها ۵. پشتیبانی از‪ localization ‬که میشه پیغام‌های فارسی مناسبی ایجاد کرد. ۶…(الان دیگه چیزی تو ذهنم نیست)

در ادامه مثالی از یک سرویس برای ساخت کامنت آمده است:

class Social::Api::V1::Comment::Create < ActiveInteraction::Base
object :current_user, class: User
string :post_uid
string :body
def execute
post = ::Post.find_by! uid: post_uid
comment = ::Comment.build_from post, current_user.id, body
comment.save
return errors.merge!(comment.errors) unless comment.valid? comment
end
end

و نحوه‌ی استفاده از سرویس تعریف شده در داخل کنترلر:

class Social::Api::V1::CommentController < ApplicationController
before_action :authorize?
def create
permitted = params.permit(:post_uid, :parent_id, :body)
.merge(current_user: @current_user)
create = Social::Api::V1::Comment::Create.run(permitted)
return render
json: create.errors.full_messages,
status: BAD_REQUEST unless create.valid?
@comment = create.result
render :show, status: CREATED
end
end

--

--