ডকুমেন্টেশনফুলস্ট্যাক ফ্রেমওয়ার্ক
রুবি অন রেল থেকে নেক্সি পর্যন্ত
নেক্সি এ রেল রুট এবং এর কন্ট্রোলার অ্যাকশন src/routes/ এর অধীনে একটি ফাইল হয়ে যায়: ERB ভিউ Jinja2 সহ .nexy পৃষ্ঠা হয়ে যায়, শক্তিশালী প্যারামিটারগুলি Pydantic মডেলে পরিণত হয় এবং before_action একটি dependencies.py হয়ে যায়।
নীচের প্রতিটি বিভাগ একটি রেল অভ্যাস দেখায়, তারপর Nexy তে একই জিনিস।
একটি রুট এবং তার কর্ম
get "/api/hello", to: "hello#show"class HelloController < ApplicationController def show render json: { message: "Hello" } endendকোন routes.rb নেই: ফাইল পাথ হল URL, ফাংশনের নাম হল HTTP পদ্ধতি।
async def GET(): return {"message": "Hello"}resources
resources :notes, only: [:index, :create, :show, :destroy]সাতটি REST অ্যাকশন দুটি ফাইলে ছড়িয়ে আছে, প্রতি URL-এ একটি:
from pydantic import BaseModel NOTES: dict[int, str] = {} class NewNote(BaseModel): title: str async def GET(): return [{"id": id, "title": title} for id, title in NOTES.items()] async def POST(note: NewNote): id = max(NOTES, default=0) + 1 NOTES[id] = note.title return {"id": id, "title": note.title}from nexy.http import HTTPException from .index import NOTES async def GET(id: int): if id not in NOTES: raise HTTPException(status_code=404, detail="No such note") return {"id": id, "title": NOTES[id]} async def DELETE(id: int): NOTES.pop(id, None) return {"deleted": id}| রেল কর্ম | নেক্সি |
|---|---|
index, create |
GET, POST notes/index.py |
show, update, destroy |
GET, PATCH, DELETE notes/[id].py |
new, edit |
.nexy পৃষ্ঠা, notes/new.nexy এবং notes/[id]/edit.nexy |
params এবং শক্তিশালী পরামিতি
def create item = params.require(:item).permit(:name, :price) render json: item, status: :createdendমডেল হল পারমিট তালিকা এবং বৈধতা: অজানা ক্ষেত্রগুলি বাদ দেওয়া হয়েছে, ভুল উত্তরগুলি 422।
from pydantic import BaseModel, Field from nexy.http import JSONResponse class NewItem(BaseModel): name: str price: float = Field(gt=0) async def POST(item: NewItem): return JSONResponse(item.model_dump(), status_code=201)একটি ক্যোয়ারী স্ট্রিং প্যারামিটার, params[:q], একটি ফাংশন প্যারামিটার:
async def GET(q: str = "", page: int = 1): return {"q": q, "page": page}namespace এবং before_action
namespace :admin do get "stats", to: "stats#show"endclass Admin::BaseController < ApplicationController before_action :require_admin private def require_admin head :forbidden unless request.headers["X-Role"] == "admin" endendনামস্থান হল ফোল্ডার, এবং এর dependencies.py হল এটির প্রতিটি রুটের before_action:
async def GET(): return {"users": 3}from nexy.http import Header, HTTPException def require_admin(x_role: str = Header("")) -> None: if x_role != "admin": raise HTTPException(status_code=403, detail="Admins only") dependencies = [require_admin]after_action এবং র্যাক মিডলওয়্যার
after_action { response.set_header("X-App", "demo") }from nexy.http import Request async def middleware(request: Request, call_next): response = await call_next(request) response.headers["x-app"] = "demo" return responseERB ভিউ
def index @users = [{ name: "Ada" }, { name: "Alan" }]end<ul> <% @users.each do |user| %> <li><%= user[:name] %></li> <% end %></ul>অ্যাকশন এবং ভিউ এক .nexy ফাইল; উদাহরণ ভেরিয়েবলগুলি সরল নাম হয়ে যায়:
users = [{"name": "Ada"}, {"name": "Alan"}]<ul> {% for user in users %} <li>{{ user.name }}</li> {% endfor %}</ul><%= %> পালিয়ে যায় এবং {{ }} করে না: একজন দর্শক {{ value | e }} দিয়ে যা টাইপ করেন তা এড়িয়ে যান। <%== %> এবং raw হল | safe।
বিন্যাস এবং yield
<!DOCTYPE html><html> <body><%= yield %></body></html>children: prop[NexyElement]<!DOCTYPE html><html> <body>{{ children | safe }}</body></html>একটি সাবফোল্ডারে একটি layout.nexy এটির ভিতরে থাকে, যেমন প্রতি কন্ট্রোলার একটি লেআউট করে।
আংশিক
<article><h2><%= title %></h2><%= yield %></article><%= render "shared/card", title: "Latest" do %><p>This week</p><% end %>
title: prop[str]<article> <h2>{{ title }}</h2> <Slot /></article>from "@/components/Card.nexy" import Card<Card title="Latest"> <p>This week</p></Card>@ হল src/: nx new লিখেছেন useAliases = {"@": "src"} nexyconfig.py।
form_with এবং redirect_to
<%= form_with url: notes_path do |form| %> <%= form.text_field :title %> <%= form.submit "Add" %><% end %>def create Note.create!(title: params[:title]) redirect_to notes_pathendএকটি কর্ম হল create ফর্ম পোস্ট করা. এর পরামিতিগুলি হল ক্ষেত্র, এবং ভিজিটরকে একটি 303 দিয়ে পৃষ্ঠায় পুনঃনির্দেশিত করা হয়:
from nexy.decorators import Action TITLES: list[str] = [] @Actionasync def add_note(title: str) -> None: TITLES.append(title)from src.actions.notes import TITLES<form method="post" action="{{ __actions_path['add_note'] }}"> <input name="title"> <button type="submit">Add</button></form><ul> {% for title in TITLES %} <li>{{ title }}</li> {% endfor %}</ul>সক্রিয় রেকর্ড এবং মাইগ্রেশন
class Post < ApplicationRecord scope :published, -> { where(published: true) }endNexy এর নিজস্ব কোন ORM নেই; nx new ভারা হতে পারে SQLModel, SQLAlchemy বা কচ্ছপ-ORM। সাথে SQLModel:
from sqlmodel import Field, SQLModel class Post(SQLModel, table=True): id: int | None = Field(default=None, primary_key=True) title: str published: bool = Falsefrom sqlmodel import Session, select from src.configs.db import enginefrom src.models.post_model import Post async def GET(): with Session(engine) as session: posts = session.exec(select(Post).where(Post.published)).all() return {"titles": [post.title for post in posts]}| রেল | নেক্সি |
|---|---|
rails generate migration AddPosts |
nx migrate -m "add posts" |
rails db:migrate |
nx migrate --upgrade |
ActiveRecord::RecordNotFound এবং public/404.html
def show @post = POSTS.fetch(params[:slug]) { raise ActiveRecord::RecordNotFound }endfrom nexy import notFound POSTS = {"hello": "Hello, world"} slug: prop[str]if slug not in POSTS: notFound()<h1>{{ POSTS[slug] }}</h1>রুট রুটে notfound.nexy হল public/404.html, যেকোনো পৃষ্ঠার মতো রেন্ডার করা হয়েছে:
<h1>Not found</h1>সেশন
def create session[:user] = params[:name] render json: { user: session[:user] }endfrom nexy.core.models import NexyConfigModel class NexyConfig(NexyConfigModel): useAliases = {"@": "src"} useSession = {"secret_key": "change-me"}from pydantic import BaseModel from nexy.http import Request class Login(BaseModel): name: str async def POST(request: Request, body: Login): request.session["user"] = body.name return {"user": body.name}একটি পৃষ্ঠা এটি useSession() দিয়ে পড়ে।
ক্যাশিং
def index expires_in 1.minute, public: trueendrevalidate = 60<h1>Blog</h1>সক্রিয় কাজ
WelcomeMailerJob.perform_later(params[:email])head :acceptedfrom nexy.http import BackgroundTasks, JSONResponse def send_welcome(email: str) -> None: ... async def POST(email: str, tasks: BackgroundTasks): tasks.add_task(send_welcome, email) return JSONResponse({"queued": True}, status_code=202)পুনরায় চেষ্টা এবং পৃথক কর্মীদের জন্য, Sidekiq এর মতো, Celery, RQ বা arq ব্যবহার করুন।
অ্যাকশন ক্যাবল
class EchoChannel < ApplicationCable::Channel def receive(data) transmit(data) endendfrom fastapi import WebSocket async def SOCKET(websocket: WebSocket): await websocket.accept() await websocket.send_text(await websocket.receive_text())হটওয়্যার
টার্বো ড্রাইভের পৃষ্ঠা অদলবদল একটি ক্লায়েন্ট-মোড প্রকল্পের ক্লায়েন্ট রাউটারের সাথে মেলে, এবং উদ্দীপক নিয়ন্ত্রক দ্বীপগুলির সাথে মেলে: একটি ছোট উপাদান যা একটি সার্ভার পৃষ্ঠার ভিতরে হাইড্রেট করে। দ্বীপ এবং CSR দেখুন।
টেস্ট
RSpec.describe "Hello", type: :request do it "says hello" do get "/api/hello" expect(response.parsed_body).to eq("message" => "Hello") endendfrom fastapi.testclient import TestClient from nexy.app import app def test_hello(): assert TestClient(app).get("/api/hello").json() == {"message": "Hello"}চলছে
| রেল | নেক্সি |
|---|---|
rails new |
nx new |
bin/rails server |
nx dev |
bin/rails routes |
/docs |
RAILS_ENV=production bin/rails server |
nx build, তারপর nx start |
bin/rails test / rspec |
nx test |