Разработка бэкенда сайта на Ruby (Ruby on Rails)

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка бэкенда сайта на Ruby (Ruby on Rails)
Средняя
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Разработка бэкенда сайта на Ruby (Ruby on Rails)

Rails остаётся одним из самых продуктивных фреймворков для команд, которым нужно быстро запустить продукт, не строя каждый слой с нуля. Conventions over configuration здесь не маркетинговый слоган — это буквально описание того, как работает кодогенерация, роутинг, ORM и тестирование.

Где Rails в форме

Контентные платформы, маркетплейсы, SaaS с многоарендностью, административные панели — там, где важнее скорость итерации, чем сырая производительность. Shopify, GitHub, Basecamp — всё это Rails под капотом при огромных нагрузках. На Rails 7 с Puma + Falcon или Unicorn нагрузка 3–5k RPS на инстанс — норма для правильно написанного приложения.

Современный стек

Rails 7.1 + Hotwire (Turbo + Stimulus) + PostgreSQL — стек, который не требует отдельного React-фронтенда для большинства задач. Для API-only режима:

# config/application.rb
module MyApp
  class Application < Rails::Application
    config.api_only = true
    config.middleware.use ActionDispatch::Cookies
    config.middleware.use ActionDispatch::Session::CookieStore
  end
end

Active Record и миграции

# db/migrate/20240315_create_orders.rb
class CreateOrders < ActiveRecord::Migration[7.1]
  def change
    create_table :orders do |t|
      t.references :user, null: false, foreign_key: true
      t.integer :status, null: false, default: 0
      t.decimal :total, precision: 10, scale: 2, null: false
      t.jsonb :metadata, default: {}
      t.timestamps
    end

    add_index :orders, :status
    add_index :orders, :created_at
    add_index :orders, [:user_id, :status]
  end
end
# app/models/order.rb
class Order < ApplicationRecord
  belongs_to :user
  has_many :items, class_name: 'OrderItem', dependent: :destroy

  enum :status, { pending: 0, paid: 1, shipped: 2, delivered: 3, cancelled: 4 }

  scope :recent, -> { order(created_at: :desc) }
  scope :for_period, ->(from, to) { where(created_at: from..to) }

  validates :total, numericality: { greater_than: 0 }

  after_update_commit :broadcast_status_change, if: :saved_change_to_status?

  private

  def broadcast_status_change
    ActionCable.server.broadcast("order_#{id}", { status: status })
  end
end

Сервисные объекты

Для бизнес-логики, которая не помещается в модель:

# app/services/orders/create_service.rb
module Orders
  class CreateService
    Result = Data.define(:success, :order, :errors)

    def initialize(user:, params:)
      @user = user
      @params = params
    end

    def call
      ActiveRecord::Base.transaction do
        order = @user.orders.build(status: :pending)
        items = build_items(order)

        order.total = items.sum { |i| i.price * i.quantity }
        order.save!
        order.items << items

        PaymentJob.perform_later(order.id)
        Result.new(success: true, order: order, errors: [])
      end
    rescue ActiveRecord::RecordInvalid => e
      Result.new(success: false, order: nil, errors: e.record.errors.full_messages)
    end

    private

    def build_items(order)
      @params[:items].map do |item_params|
        product = Product.find(item_params[:product_id])
        OrderItem.new(
          order: order,
          product: product,
          price: product.current_price,
          quantity: item_params[:quantity]
        )
      end
    end
  end
end

Контроллер и сериализация

# app/controllers/api/v1/orders_controller.rb
module Api
  module V1
    class OrdersController < ApplicationController
      before_action :authenticate_user!

      def index
        orders = current_user.orders.recent.page(params[:page]).per(25)
        render json: OrderSerializer.new(orders, { meta: pagination_meta(orders) })
      end

      def create
        result = Orders::CreateService.new(
          user: current_user,
          params: order_params
        ).call

        if result.success
          render json: OrderSerializer.new(result.order), status: :created
        else
          render json: { errors: result.errors }, status: :unprocessable_entity
        end
      end

      private

      def order_params
        params.require(:order).permit(items: [:product_id, :quantity])
      end
    end
  end
end

Сериализация через jsonapi-serializer:

class OrderSerializer
  include JSONAPI::Serializer

  attributes :status, :total, :created_at

  has_many :items, serializer: OrderItemSerializer
  belongs_to :user, serializer: UserSerializer
end

Фоновые задачи с Sidekiq

# app/jobs/payment_job.rb
class PaymentJob < ApplicationJob
  queue_as :payments
  sidekiq_options retry: 3, backtrace: 5

  def perform(order_id)
    order = Order.find(order_id)
    return if order.paid?

    result = Payments::StripeService.new(order).charge

    if result.success?
      order.paid!
    else
      order.cancelled!
      raise PaymentFailedError, result.error_message
    end
  end
end
# config/sidekiq.yml
concurrency: 10
queues:
  - [payments, 3]
  - [mailers, 2]
  - [default, 1]

Кэширование

# Russian-cache через Redis
def cached_categories
  Rails.cache.fetch("categories/all", expires_in: 1.hour) do
    Category.active.includes(:children).to_a
  end
end

# Фрагментное кэширование в API
def index
  categories = Rails.cache.fetch_multi(*Category.active.pluck(:id).map { "category/#{_1}" }) do |key|
    id = key.split('/').last.to_i
    Category.find(id)
  end
  render json: categories.values
end

Тестирование

# spec/services/orders/create_service_spec.rb
RSpec.describe Orders::CreateService do
  let(:user) { create(:user) }
  let(:product) { create(:product, price: 99.99) }

  describe '#call' do
    subject(:result) do
      described_class.new(user: user, params: { items: [{ product_id: product.id, quantity: 2 }] }).call
    end

    it 'creates order with correct total' do
      expect(result.success).to be true
      expect(result.order.total).to eq(199.98)
    end

    it 'enqueues payment job' do
      expect { result }.to have_enqueued_job(PaymentJob)
    end
  end
end

Деплой

Puma в кластерном режиме + Nginx как реверс-прокси — стандартная схема. Kamal (от Basecamp) упрощает деплой в Docker без Kubernetes:

# config/deploy.yml (Kamal)
service: myapp
image: registry.example.com/myapp

servers:
  web:
    hosts: [10.0.0.1, 10.0.0.2]
    options:
      memory: 512m
  workers:
    hosts: [10.0.0.3]
    cmd: bundle exec sidekiq

env:
  secret: [RAILS_MASTER_KEY, DATABASE_URL, REDIS_URL]

Сроки

API для мобильного приложения (аутентификация, 10–15 ресурсов, Sidekiq): 1–2 недели. Полноценный SaaS-бэкенд с многоарендностью, подписками, вебхуками и развитой логикой: 4–6 недель. Рефакторинг Rails 4/5 на 7.1 с обновлением гемов — зависит от объёма, обычно 2–3 недели на аудит и патчинг.