Rails Console Json Data

레일스 콘솔에서 데이터 편하게 보는법.

일단 그냥 보면 되지 굳이 명령어하나 더 치면서 데이터를 확인할까 하지만 데이터가 너무 길고 보기 힘들때 이해도 못하는 데이터 보기라도 편하게 바꿔보자 싶어서 찾아보았다.

먼저 일반적으로 보던 모습이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{"id"=>321312312,
"product_id"=>5858457321321223335,
"title"=>"",
"price"=>"17000",
"sku"=>"H59554J1S16C",
"position"=>16,
"inventory_policy"=>"deny",
"compare_at_price"=>nil,
"fulfillment_service"=>"manual",
"inventory_management"=>"shopify",
"option1"=>"brown",
"option2"=>"-4.25",
"option3"=>nil,
"created_at"=>"2020-09-28T16:44:30+09:00",
"updated_at"=>"2022-03-31T23:36:06+09:00",
"taxable"=>true,
"barcode"=>"8809693505654",
"grams"=>37,
"image_id"=>20065729413287,
"weight"=>37.0,
"weight_unit"=>"g",
"inventory_item_id"=>38760799502503,
"inventory_quantity"=>996,
"old_inventory_quantity"=>996,
"requires_shipping"=>false,
{"id"=>36712615346343,
"product_id"=>5858457223335,
"title"=>"brown / -4.50",
"price"=>"17000",
"sku"=>"H59554J1S17C",
"position"=>17,
"inventory_policy"=>"deny",
"compare_at_price"=>nil,
"fulfillment_service"=>"manual",
"inventory_management"=>"shopify",
"option1"=>"brown",
"option2"=>"-4.50",
"option3"=>nil,
"created_at"=>"2020-09-28T16:44:30+09:00",
"updated_at"=>"2022-03-31T23:36:07+09:00",
"taxable"=>true,
"barcode"=>"8809693505661",
"grams"=>37,
"image_id"=>20065729413287,
"weight"=>37.0,
"weight_unit"=>"g",
"inventory_item_id"=>38760799535271,
"inventory_quantity"=>999,
"old_inventory_quantity"=>999,
"requires_shipping"=>false,
"admin_graphql_api_id"=>"gid://shopify/ProductVariant/36712615346343",
"compare_at_price2"=>""},

Ruby on Rails Grape Gem

루비 온 레일스 Grape Gem 사용하기

Grape 젬은 레일스 환경에서 REST 와 유사한 API 프레임워크이다.

Grape GitHub
Grape Gem GitHub HomePage

Install Gem

1
2
# Gemfile
gem 'grape'

Gemfile 에 grape 젬을 추가해준뒤 bundle install 명령어를 실행한다.

설정하기

적용하기 위한 프로젝트의 레일스 버전이 7버전으로 grape github README 를 따라 6버전 이상의 세팅 방법을 따라 진행 하였다.

path: ./config/initializers/inflections.rb
아래의 코드가 이미 작성되어있고 주석처리가 되어있다. 해당부분 주석을 제거하고 작성해주면 된다.

1
2
3
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym "DefaultController" # 베이스가 되는 클래스의 이름을 입력하는 부분이다.
end

컨트롤러 생성

1
2
3
4
cd app
mkdir api
touch base_api.rb
touch default_controller.rb

path: ./app/api/base_api.rb

1
2
3
4
5
6
7
8
class BaseApi < Grape::API
# 기타 공용 함수들?
helpers do
def server_port
Rails.env['PORT'] || 3000
end
end
end

path: ./app/api/default_controller.rb

1
2
3
4
5
6
7
8
9
class DefaultController < BaseApi
version 'v1', using: :path
format :json
prefix :api

get 'alive' do
"rails server run #{server_port} port"
end
end

path: ./config/routes.rb

1
2
3
4
Rails.application.routes.draw do
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
mount DefaultController => '/'
end

curl을 이용하여 요청하기


User Controller 생성하기

1
2
3
# work dir: ./app
cd user_controller
touch user_api.rb

path: ./app/api/user_controller/user_api.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
module UserController
class UserApi < BaseApi

resource 'users' do
helpers do
def post_params
params.as_json(only: %i[email password name nick_name age gender])
end
end
# GET /api/v1/users/all
get 'all' do
users = User.all
{
total: users.count,
result: users.map { |r| Entities::UserEntity.represent(r) },
}
end

# POST /api/v1/users
post do
user = User.create(post_params)
present user, with: Entities::UserEntity
end
end
end
end

POST /users


GET /users/all


Ruby on Rails Docker Setting (레일스 도커 개발환경 세팅하기)

Ruby on Rails Docker Setting

레일스 개발 환경을 도커로 세팅해보자

크게 복잡하고 거창한 환경 세팅은 아니지만 처음 세팅이 항상 골칫거리이다..

개발 환경
ruby-on-rails -v 7.0^
ruby -v 2.7.1
RubyMine
Docker
docker-compose
postgres -v 14.2-alpine

1. 기본 세팅을 위한 파일 생성 및 작성

1
2
3
4
5
6
mkdir backend
cd backend

touch Dockerfile
touch docker-compose.yml
touch docker-compoes.env

Dockerfile 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# syntax=docker/dockerfile:1
FROM ruby:2.7.1

RUN apt-get update -qq && apt-get install -y nodejs postgresql-client

WORKDIR /usr/src/app
COPY Gemfile ./
COPY Gemfile.lock ./
RUN bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]

docker-compose.yml 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: "3"
services:
## backend
database:
image: postgres:14.2-alpine
ports:
- "5432:5432"
env_file: docker-compose.env
volumes:
- ./psql/data:/var/lib/postgresql/data

## api
web:
container_name: web
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
ports:
- "3000:3000"
env_file: docker-compose.env
volumes:
- ./:/usr/src/app
depends_on:
- "database"
environment:
- RAILS_ENV=development

Gemfile, Gemfile.lock 생성

1
2
touch Gemfile
touch Gemfile.lock
1
2
3
4
# Gemfile
source "https://rubygems.org"

ruby "2.7.1"

docker-compose.env

1
2
3
4
5
POSTGRES_USER=user
POSTGRES_PASSWORD=password

PG_USER=user
PG_PASSWORD=password

2. 빌드 시작

1
docker-compose build

빌드를 시작해도 아직 레일스 세팅이 안되어있다. docker 컨테이너를 이용하여 레일스 설치를 진행한다.

1
docker-compose run --no-deps web rails new . --api --force --database=postgresql

실행 시 뭔가 쭉쭉 설치되고 로컬 디렉토리와 컨테이너 볼륨을 지정해줬기 때문에 작업 디렉토리에 레일스 폴더, 파일들이 생성된다.



3. database.yml 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# ./config/database.yml

default: &default
adapter: postgresql
encoding: utf8
# For details on connection pooling, see Rails configuration guide
# https://guides.rubyonrails.org/configuring.html#database-pooling
pool: 5
host: database # docker 환경 데이터베이스와 연결을 하기위해서는 컨테이너 이름으로 지정해주어야 한다.
username: juren
password: juren

development:
<<: *default
database: juren_development

test:
<<: *default
database: juren_test

4. 데이터베이스 생성하기

아직 도커에서 실행중인 postgresql 에는 데이터베이스가 생성되어있지 않다. yml 파일에서 지정한 데이터베이스들을 생성해주기 위해서는 아래 명령어를 실행한다.

1
2
docker-compsoe up # 컨테이너 실행 명령어
docker-compose run web rake db:create # rails db 생성 명령어

5. localhost 접속

크롬 -> localhost:3000 접속 결과 확인



끝~👍👍

은 아니고 이제 시작...

Ruby 메서드

루비 메서드

메서드 정의

메서드는 def 키워드로 정의하며 이름의 마지막에는 !, ?, = 를 사용할 수 있다. 각각의 키워드는 다음과 같이 사용된다.

  1. True, False를 반환하는 메서드의 경우 ?를 사용하기도 한다.
  2. 수신자의 값을 바꿔버리는 메서드의 경우 !를 사용한다. 이러한 메서드는 뱅 메서드라고 불린다.
  3. 대입문의 좌측에 올 수 있는 메서드이름 마지막에 = 기호를 사용한다.

가변 인자 리스트

개수가 정해지지 않은 가변 매개변수를 전달하거나 하나의 매개변수로 여러개의 매개변수를 처리한다면 메서드 인자의 마지막에 가변매개변수 앞에 *기호를 사용하면 된다.

1
2
3
4
5
6
7
def method_1(arg_1, *rest)
"arg_1 = #{arg_1}, rest = #{rest.inspect}"
end

pp method_1("one") # => "arg_1 = one, rest = []"
pp method_1("one", "two") # => "arg_1 = one, rest = [\"two\"]"
pp method_1("one", "two", 1) # => "arg_1 = one, rest = [\"two\", 1]"

첫 번째 매개변수는 일반적인 매개변수로 지정되고 두 번쨰 매개변수에 *기호가 붙어있기 때문에 남은 매개변수 모두를 Array객체에 저장하여 매개변수에 대입한다.

이러한 가변 매개변수는 메서드에서 직접 사용하지는 않지만 상위 클래스에서 같은 이름을 가지고 있는 메서드를 호출하고자 하는 경우에 사용되기도 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Parent
def do_something(*)
pp "parent class"
end
end

class Child < Parent
def do_something(*)
super
end
end

a = Child.new
a.do_something # => "parent class"

메서드와 블록

메서드를 호출할때 블록을 결합시켜 호출을 할 수 있다. 이러 방식으로 결합된 메서드는 내부에서 yield를 사용하여 호출이 가능하다.

1
2
3
4
def some(arg_1)
yield(arg_1 + 1)
end
some(1) { |value| pp "value : #{value}" } # => 2

이러한 방식으로도 사용이 가능하지만 매개변수 앞에 & 기호를 붙여주면 Proc 객체로 변환되어 이 객체를 마지막 매개변수에 대입하여 사용할 수 있다.

1
2
3
4
def proc(arg_1, &proc)
proc.call(arg_1)
end
proc(1) { |v| pp v * 10 } # => 10

루비 메서드 결과 반환

루비 메서드는 일반적으로 결과를 반환한다. 무조건 반환하는 것은 아니다. 하지만 결과를 반환하는 메서드에서 결과값은 일반적으로 마지막으로 실행된 표현식의 결과값이다.
대부분 return 문을 작성하지 않아도 되지만 메서드 실행 중간 빠져나가야 한다면 return 문을 사용하는 경우도 있다.

1
2
3
4
5
6
7
8
def re
100.times do |i|
value = i * i
return i, value if value > 1000
end
end
v = re
pp v # => [32, 1024]

루비에서는 두개 이상의 결과를 return 하게 되면 배열 형태로 결과값을 반환하게 된다. 이런식으로 반환된 Array 값은 병렬 대입문으로 값을 이용 할 수 있다.

1
2
3
4
5
6
7
8
9
def re
100.times do |i|
value = i * i
return i, value if value > 1000
end
end
index, value = re
pp index # => 32
pp value # => 1024

Ruby 정규표현식

정규표현식
그동안 공부를 하면서 서버에서 정규 표현식을 사용하는 일이 얼마나 있을까? 라는 의문과 필요하면 그때그때 찾아보면서 해도 상관없겠다 라는 마음으로 미루고 미룬 것 중 하나가 정규표현식이였다.
간단한 코딩 테스트 문제에서도 등장했던 정규표현식인데 항상 마주하면 생각만큼 쉽지 않고 복잡한 정규표현식…
왜 정규표현식이 서버 코드에서 사용하는 일이 많지 않을 것이라고 생각했는지 의문이 들 정도로 회사 프로젝트에서 정규표현식의 필요성이 느껴졌다. 가장 많이 사용하는 곳은 Rspec을 활용한 테스트 케이스 코드 그리고 파일을 읽고 쓰는 과정에서 항상 등장하는 정규표현식..

그래서 기본적인 정규표현식의 형태에 대해 알아보고자 정규표현식을 학습해보고자 한다. 모든 언어에서 정규표현식을 지원하지만 주로 사용하는 언어가 루비와 자바스크립트인 만큼 그리고 회사 백엔드 코드는 루비로 이루어져있기 때문에? 루비 기준으로 루비에서는 어떤 방식으로 정규표현식이 이루어 지는지 알아보았다.

정규표현식이란?
정규표현식이란 특정한 규칙을 가진 문자열의 집합을 표현하는 데 사용하는 형식 언어이다.

정규 표현식을 사용해야 하는 이유는 여러가지가 있겠지만 직접 직면한 문제에서 느낀점은 수많은 데이터 혹은 문자들에서 원하는 패턴의 문자열을 매칭하고 치환하는 작업을 할때 정규표현식을 모른다면?
일일히 원하는 결과를 위한 메서드를 만들어야 할 것이다. 하지만 정규표현식을 통한 연산을 통해 원하는 값을 얻고 변환하며 결과를 가지고 조건문에서 사용이 가능해진다면
하나하나 메서드를 만들 필요도 없고 생산성이 좋아진다. 물론 이런 작업을 위해 그래도 난 메서드를 만들어 보겠다는 사람이 굳이 존재할까 싶지만 정규표현식을 활용하여 많은 작업과 처리가 이루어 질 수 있기 때문에 기본적인 정규표현식에대해 학습해보고자 한다.

자세히 보기

Ruby 파일 읽기,쓰기

루비에서 파일 읽기, 쓰기

루비에서는 파일 및 디텍토리 입출력을 위하여 File, Dir클래스를 제공하고 있다.

###File
File 클래스는 다양한 메서드를 통해 파일을 읽고 쓰고 할 수 있으며 다양한 방식으로 활용이 가능하다.
회사 프로젝트에서 File 클래스를 주로 사용하게 되었던 부분은 이미지 파일을 읽고 AWS S3에 업로드 할 때 혹은 어드민에서 엑셀 데이터를 활용, 생성하기 위해 주로 사용하였다.

File 클래스에 대한 다양한 기능은 문서를 통해 학습하고 필요한 기능을 사용하면 되겠다.

File Class Docs
https://ruby-doc.org/core-2.5.0/File.html

포스트에서는 사용했던 메서드와 간단한 사용방법에 대해 기록하고자 한다.

  1. 파일 읽기.
    가장 중요한 읽기이다. 파일을 읽기 위해서는 File.open, File.new 이라는 메서드를 사용한다. 사용방법은 간단하며 다음과 같이 실행한다.
1
2
File.open(filename, option)
File.new(filename, option)

new 메서드와 open 메서드의 동작 결과는 동일하게 흘러간다. 하지만 open 메서드를 사용하면 코드 블록을 통한 작업이 가능해진다.

option 값으로 설정할 수 있는 값은 다음과 같다.

옵션 설명
r 읽기 전용 모드로 파일을 연다.
r+ 읽기,쓰기 모드로 파일을 연다.
w 쓰기 전용 모드로 파일을 연다. 단 파일이 존재한다면 덮어쓴다. 그리고 파일이 없다면 새로 생성한다.
w+ 읽기, 쓰기 모드로 파일을 연다. 단 파일이 존재한다면 덮어쓴다. 그리고 파일이 없다면 새로 생성한다.
a 쓰기 전용으로 연다. 파일이 존재한다면 파일의 끝을 가르키며 없으면 생성한다.
a+ 읽기 쓰기 모드로 연다. 파일이 존재한다면 끝을 가르키고 없다면 생성한다.

  1. 폴더 읽기
    폴더를 읽기 위해서는 Dir class를 활용한다.
1
Dir.new(path)

방식은 파일 클래스와 동일하다. 주로 디렉토리를 읽고 파일을 생성하거나 내부의 파일들을 활용하기 위해 사용되는 것 같다.

디렉토리 내부의 특정 파일을 열기위해 사용하게 되었는데 만약 어떤 경로의 내부에 있는 파일 모두 혹은 특정 파일들만 찾기 위해서는 다음과 같이 사용한다.

1
2
3
4
5
# 이미지 파일만 가져오도록 한다. 확장자는 png파일만
Dir.glob("./tmp/hexo_blog/*.png") do |path|
File.open(path)
...
end

cdn 링크를 통한 이미지 파일을 실행하기 위해서 두가지 클래스들을 활용하며 느낀점은 파일 읽고 쓰기 간단하다고 생각했지만 막상 자주 사용하지 않다보니 다소 어려움이 있었다.

가장 어려웠던 cdn 링크 이미지 파일 열기…

고민하고 구글링을 통해 찾아낸 방법…이다.

1
2
3
4
5
6
7
8
image_path = "https://ifh.cc/g/jmG8MF.jpg"
filename = image_path.split(/[\/]/)[-1].split('?')[0] # 파일 이름만 잘라낸다.
stream = URI.open(image_path) # URI 클래스를 통해 url을 열어준다. 결과값은 strem형식으로 출력이 된다.
File.open("./tmp/#{filename}", 'w+b') do |file| # 해당 경로에 파일이 당연히 없으니 w+ 옵션으로 생성하게 될것이다.
stream.respond_to?(:read) ? IO.copy_stream(stream, file) : file.write(stream) # 스트림형식의 파일을 읽던지 생성하게 끔 하여 파일을 실행한다.
img = URI.open(file)
...
end

이런 방식으로 이미지를 실행하고 생성하며 업로드 등의 작업을 수행할 수 있다.

연휴 전 마지막 평일이라 그런가… 정리 퀄리티가 평소에도 막장이였는데.. 오늘은 더 심한것 같다.. 그래도 이번주 야근하면서 얻어낸? 결과 중 한가지를 기록하고자 마음먹고 기록을 하게 되었다는 것에 의미를 부여하자…
다음 포스트는 루비에서 엑셀 쓰기,읽기 관련하여 기록 예약… 요거 참 골때리고 간단하지만 복잡미묘한 그런 작업…

루비 시작하기

자바스크립트 공부를 하며 Node.js 백엔드 개발을 경험해오며 개발자로 성장하기 위해 달려왔다. 면접을 보며 입사하기로 하게 된 기업에서 자바스크립트 스택을 보고 지원했는데 루비 온 레일스를 사용하는 기업이였고 그에 따라 새로운 언어를 배워야 하는 상황이다. 학교에서 자바를 잠깐 배운것 외에는 자바스크립트 외의 언어를 경험해보지 못했는데 새로운 언어와 프레임워크를 경험하게 되어 좋은 경험이 될것 같다는 생각이 든다.😂

📩 Ruby Git Repo

루비는 어떤 언어인가?

루비를 공부 해봐야겠다고 생각한 후 루비는 어떤 언어인가를 가장 먼저 알아 보게 되었다. 루비 홈페이지를 찾아보니 루비에 대해 다음과 같이 설명해 주고 있었다.

  1. 루비는 순수 객체 지향 언어이다.
  2. 루비의 모든 것은 객체로 분류된다.
  3. 루비는 유연한 언어이다.
  4. 다른 객체 지향 언어와 달리 의도적인 단일 상속만을 제공한다. 대신 모듈 기능을 이용하여 필요한 메서드를 사용할 수 있다.

루비는 모든 것을 객체로 분류한다는 특징이 가장 생소하지만 흥미롭게 다가왔다. 자바스크립트 처럼 원시타입과 참조타입을 분류하지 않고 모든것을 객체로 분류한다는 것이 새로운 언어를 배우기 시작하는 단계에서 흥미를 불러와 주었다.

그렇다면 왜 루비인가

왜 루비를 사용하는지 궁금했다. 웹개발이라 하면 자바스크립트, 파이썬, 자바 3가지를 생각하고 루비라는 언어를 들어만 봤지 실질적으로 접하는 기회가 없었기 때문이다.
루비를 사용하여 웹 개발을 진행 할 때 루비 온 레일스라는 프레임워크를 사용한다고 한다.
루비를 사용하는 가장 보편적인 이유는 쉽고 개발 생산성이 빠르다. 라고 많이 얘기를 하는 것 같다. 아직 루비 기본 문법을 보며 따라하는 단계에서는 느끼지 못했지만
Express를 사용하여 개발을 할때의 장점과 비슷한 느낌이지 않을까 넘겨짚어 생각하게 된다. 왜 루비를 사용하는지 회사에 물어보면 그럴듯한 답변이 올지 궁금한데 사실 못 물어 보겠다….

자세히 보기