Ruby on Rails
Introduction
Rails(Ruby on Rails, RoR)는 Ruby의 대표적인 프레임워크로 MVC 모델을 사용하는 풀스택 웹 프레임워크입니다. Ruby 특유의 쉽고 직관적인 문법으로 인해 Rails 또한 코드를 이해하는데 어렵지 않으며 scaffold 등의 기능으로 빠르게 웹 서비스를 구성할 수 있습니다.
이외에도 웹 서비스를 개발하는데 있어 필요한 여러가지 기술, 테크닉, 보안에 대한 부분이 많이 고려되어 있습니다.
Installation
sudo gem install rails
Struct of Rails app
Model
- config/database.yml : DB 접속정보 및 설정
- db/migrate/* : active_record 관련 코드
- app/models/* : model(db schema)에 관련된 코드
View
- app/views/* : Model, Controller와 연결된 View 코드들
Controller
- app/controllers/* : 컨트롤러 코드
- config/routes.rb : 실제 라우팅이 명시되는 코드
Etc
- config/* : 어플리케이션에 대한 설정들
- public/* : public 디렉토리
Snippet
New Web App
rails new {appname}
With TailWind
rails new {appname} --css tailwind
Specifies the DB
rails new {appname} --database=postgresql
New API App
rails new {appname} --api
or
# config/application.rb
config.api_only = true
Generate with scaffold
scaffold는 한번에 명령으로 MVC(Model, View, Controller)를 한번에 생성할 수 있는 기능입니다.
rails g scaffold post title:string context:text
types
- string
- text (long text, up to 64k, often used for text areas)
- datetime
- date
- integer
- binary
- boolean
- float
- decimal (for financial data)
- time
- timestamp
- references
Migration
New model
rails g model Scans name:string url:string
Migration
rake db:migrate
Rollback
rake db:rollback # 가장 최근 DB 상태로 되돌립니다.
rake db:rollback STEP=2 # 2번 Undo 하여 DB 상태를 되돌립니다.
Redo
rake db:migrate:redo STEP=3
# rollback 후 다시 migration 합니다. STEP으로 task를 조정할 수 있습니다.
Add column
rails g migration add_columns_from_model
# Example
rails g migration add_content_from_post
Change column type
rails g migration ChangeColumnType
class ChangeColumnType < ActiveRecord::Migration[7.0]
def change
change_column :users, :age, :integer
end
end
ERD
rails-erd 포함 후 rake erd로 현재 model에 대한 erd를 볼 수 있습니다.
gem 'rails-erd'
rake erd
Run Server
rails s
rails server
Run Console
Rails는 console 명령을 통해 실행중인 앱에서 직접 데이터를 처리하거나 코드 스니펫을 실행할 수 있습니다.
rails c
rails console
with env
rails console -e <env>
# rails console -e developement
# rails console -e production
with sandbox mode
rails console --sandbox
sandbox 모드로 동작하면 테스트로 인해 DB 변경이 일어나도 console이 종료될 때 롤백됩니다.
🎮 Codes
Caching
Low Level Caching
# Read
value1 = Rails.cache.read 'cache_key'
value2 = Rails.cache.read({key: 'sequence', owner: @user})
## 값이 있다면 값을 return, 없거나 만료됬다면 nil을 리턴
# Write
Rails.cache.write 'cache_key', some_data
Rails.cache.write 'cache_key', some_data, expires_in: 3.hour
# Fetch
Rails.cache.fetch('cache_key', expires_in: 30.minutes) do
# Code..
end
Active Record
Relationship
사용 가능한 Relation은 아래와 같으며 이를 이용하면 서비스의 구성에 따라 단순한 모델부터 Polymorphic 등 복잡한 형태의 Relationship을 구성할 수 있습니다. 이는 Model에 직접적으로 연관되며 데이터를 처리하는데 있어서 큰 이점을 가져옵니다.
belongs_to # 1:1 (한 모델이 다른 모델에 속할 때)
has_one # 1:1 (한 모델이 다른 모델을 가지고 있을 때)
has_many # 1:N (한 모델이 다른 모델을 여러개 가지고 있을 때)
has_many :through # M:N (제3의 모델로 M:N의 간접 관계를 가질 때)
has_one :through # 1:1 (제3의 모델로 간접적 관계를 가질 때)
has_and_belongs_to_many # M:N (M:N의 모델이 관계를 가질 때)
e.g
class Customer < ActiveRecord::Base
has_many :orders
end
# Customer는 여러개의 Order를 가짐
with scaffold
rails g scaffold Order data:string customer:references
# rails c
irb(main):001:0> Order.create data:"aa", customer_id:4
#<Comment:0x00000001095fbea0
id: 2,
data: "aa",
customer_id: 4,
created_at:
Wed, 10 Aug 2022 14:35:07.140636000 UTC +00:00,
updated_at:
Wed, 10 Aug 2022 14:35:07.140636000 UTC +00:00>
ActiveJob
- https://github.com/basecamp/solid_queue
- https://github.com/bensheldon/good_job
- https://github.com/sidekiq/sidekiq
- https://github.com/collectiveidea/delayed_job
ActiveSupport
ActiveSupport::Cache::Store
Hotwire
- https://github.com/hotwired/turbo
- https://github.com/hotwired/stimulus
- https://github.com/hotwired/strada-web
- https://github.com/hotwired/strada-ios
- https://github.com/hotwired/strada-android
Security
CORS
gem 'rack-cors'
# config/application.rb
config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'localhost:3000', '127.0.0.1:3000',
/\Ahttp:\/\/192\.168\.0\.\d{1,3}(:\d+)?\z/
resource '*', headers: :any, methods: [:get, :post, :options]
end
end
Blocking & Throttling
https://github.com/rack/rack-attack
e.g
throttle('logins/ip', limit: 5, period: 20.seconds) do |req|
if req.path == '/login' && req.post?
req.ip
end
end
Security Guide
- https://guides.rubyonrails.org/security.html
- https://owasp.org/www-pdf-archive//Rails_Security_2.pdf
🚂 Middlewares
https://github.com/coopermaa/awesome-rack
Articles
Rails 작성 글은 검색 링크로 대체합니다.
https://www.hahwul.com/search/?keyword=rails
💼 Resources
References
- https://guides.rubyonrails.org/getting_started.html
- https://guides.rubyonrails.org/security.html
- https://owasp.org/www-pdf-archive//Rails_Security_2.pdf