Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6ffdb56
fix: update Dockerfile to create user and set permissions for app dir…
shigenius Sep 28, 2025
a7b3a14
add rspec
shigenius Sep 28, 2025
fe562c2
add models and seeds
shigenius Sep 28, 2025
7f4c538
usage_charges.usage_lowerをnull: falseに変更
shigenius Sep 28, 2025
61af931
BasicFeeとUsageChargeのscope追加。rspec周りのgem追加
shigenius Sep 28, 2025
fbd5c5a
annotate導入
shigenius Sep 28, 2025
8346e6d
Add comments to database tables for better clarity
shigenius Sep 28, 2025
26fe673
ビジネスロジック完成
shigenius Sep 28, 2025
ffcb7e7
GET /plan/prices 実装
shigenius Sep 28, 2025
fbf1658
Fix context description
shigenius Sep 28, 2025
1432e4b
view実装
shigenius Sep 29, 2025
c586e26
Update button text for clarity in simulation form
shigenius Sep 29, 2025
bc5c5ae
remove debug
shigenius Sep 29, 2025
aba0c62
remove debug
shigenius Sep 29, 2025
2d388e3
style
shigenius Sep 29, 2025
cf95668
fix README
shigenius Sep 29, 2025
62f7f54
Update README.md
shigenius Oct 1, 2025
469da2a
fix comment
shigenius Oct 2, 2025
3db30ec
Merge branches 'master' and 'master' of github.com:shigenius/enechang…
shigenius Oct 2, 2025
2b0e6a1
model validations
shigenius Oct 2, 2025
eeddc9e
fix usage_charges index
shigenius Oct 2, 2025
84c7430
fix comment
shigenius Oct 2, 2025
61588c2
refactor plan_spec
shigenius Oct 2, 2025
6b19b85
refactor: rename createRow to buildRow for consistency
shigenius Oct 2, 2025
b7a6840
add erd
shigenius Oct 2, 2025
c09a096
fix: add missing newline at end of providers.csv
shigenius Oct 2, 2025
6210eb1
add setup.sh
shigenius Oct 2, 2025
011302f
newline
shigenius Oct 2, 2025
7a2df9d
Bug: Test Description Mismatch in Charge Spec
shigenius Oct 4, 2025
9d73b04
feat: add uniqueness validation for ampere in BasicFee and overlappin…
shigenius Oct 4, 2025
a820c4f
fix: remove unnecessary backslash in usage_charge_spec
shigenius Oct 4, 2025
5518ac9
不要なTODOコメントを削除
shigenius Oct 6, 2025
094eb4d
pk,fkをcodeに変更
shigenius Oct 6, 2025
e6f0a8b
fix: 従量料金の計算ロジックを累積計算に。またcharge_usagesのlower_usageの定義を変更
shigenius Oct 7, 2025
8a3a83a
update erd
shigenius Oct 7, 2025
cbec282
fix: change basic_fee assignment to use sole method for clarity
shigenius Oct 7, 2025
8aa50fc
add comment
shigenius Oct 7, 2025
80da434
UsageCharge#calc_chargeを少し改良。あとコメント修正
shigenius Oct 7, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions serverside_challenge_2/challenge/.rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
12 changes: 8 additions & 4 deletions serverside_challenge_2/challenge/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
FROM ruby:3.1.2
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs vim

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs vim graphviz
RUN useradd -ms /bin/bash rails
RUN mkdir /app
# Gemfile をコピー(権限を rails に変更)
COPY --chown=rails:rails Gemfile Gemfile.lock /app/
USER rails
WORKDIR /app
ADD Gemfile /app/Gemfile
ADD Gemfile.lock /app/Gemfile.lock
RUN bundle install
ADD . /app
# アプリ本体をコピー(rails ユーザーに所有権)
COPY --chown=rails:rails . /app
9 changes: 9 additions & 0 deletions serverside_challenge_2/challenge/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,22 @@ gem "bootsnap", require: false
# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
# gem "rack-cors"

gem "importmap-rails"
gem "stimulus-rails"
gem "propshaft"

group :development, :test do
# See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem
gem "debug", platforms: %i[ mri mingw x64_mingw ]
gem 'rspec-rails', '~> 6.0'
gem 'shoulda-matchers', '~> 5.0'
gem 'factory_bot_rails'
gem "rails-erd"
end

group :development do
# Speed up commands on slow machines / big apps [https://github.com/rails/spring]
# gem "spring"
gem 'annotate'
end

55 changes: 55 additions & 0 deletions serverside_challenge_2/challenge/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,34 @@ GEM
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
annotate (3.2.0)
activerecord (>= 3.2, < 8.0)
rake (>= 10.4, < 14.0)
bootsnap (1.18.3)
msgpack (~> 1.2)
builder (3.2.4)
choice (0.2.0)
concurrent-ruby (1.2.3)
crass (1.0.6)
date (3.3.4)
debug (1.9.1)
irb (~> 1.10)
reline (>= 0.3.8)
diff-lcs (1.6.2)
erubi (1.12.0)
factory_bot (6.5.5)
activesupport (>= 6.1.0)
factory_bot_rails (6.5.1)
factory_bot (~> 6.5)
railties (>= 6.1.0)
globalid (1.2.1)
activesupport (>= 6.1)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
importmap-rails (2.2.2)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
io-console (0.7.2)
irb (1.11.2)
rdoc
Expand Down Expand Up @@ -112,6 +126,10 @@ GEM
nokogiri (1.16.2-x86_64-linux)
racc (~> 1.4)
pg (1.5.4)
propshaft (1.3.1)
actionpack (>= 7.0.0)
activesupport (>= 7.0.0)
rack
psych (5.1.2)
stringio
puma (5.6.8)
Expand All @@ -138,6 +156,11 @@ GEM
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-erd (1.7.2)
activerecord (>= 4.2)
activesupport (>= 4.2)
choice (~> 0.2.0)
ruby-graphviz (~> 1.2)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
Expand All @@ -153,6 +176,30 @@ GEM
psych (>= 4.0.0)
reline (0.4.2)
io-console (~> 0.5)
rexml (3.4.4)
rspec-core (3.13.5)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.5)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.5)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.6)
ruby-graphviz (1.2.5)
rexml
shoulda-matchers (5.3.0)
activesupport (>= 5.2.0)
stimulus-rails (1.3.4)
railties (>= 6.0.0)
stringio (3.1.0)
thor (1.3.0)
timeout (0.4.1)
Expand All @@ -168,11 +215,19 @@ PLATFORMS
x86_64-linux

DEPENDENCIES
annotate
bootsnap
debug
factory_bot_rails
importmap-rails
pg (~> 1.1)
propshaft
puma (~> 5.0)
rails (~> 7.0.8)
rails-erd
rspec-rails (~> 6.0)
shoulda-matchers (~> 5.0)
stimulus-rails
tzinfo-data

RUBY VERSION
Expand Down
86 changes: 62 additions & 24 deletions serverside_challenge_2/challenge/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,62 @@
# README

This README would normally document whatever steps are necessary to get the
application up and running.

Things you may want to cover:

* Ruby version

* System dependencies

* Configuration

* Database creation

* Database initialization

* How to run the test suite

* Services (job queues, cache servers, search engines, etc.)

* Deployment instructions

* ...
# これは
電気料金のシミュレーションを行えるサービスです。

# 構成
- Back-end
- Ruby 3.1.2, Ruby on Rails 7.0.8
- DB
- PostgreSQL
- Front-end
- erb, Stimulus, CSS
- Asset
- importmap, propshaft
- Test
- Rspec, FactoryBot, Shoulda Matchers
- Dev
- annotate, rails-erd

# 開発環境
## 初回セットアップ
```sh
./scripts/setup.sh
```

- DB作成
- seedデータ作成
- railsサーバー起動

まで

## 電気料金のシミュレーション

http://localhost:3000/plans にアクセス

## 基本コマンド
### railsサーバー起動
```sh
docker compose up -d
```

### データベース初期化、seedデータ作成
```sh
docker compose run --rm web rails db:reset
```

### rspec実行
```sh
docker compose run --rm web rspec
```

# ドキュメントの更新

annotationの強制更新 ※ 基本的にmigrate実行時に更新されるので通常は不要

```sh
docker compose run --rm web bundle exec annotate --force
```

`erd.pdf`の更新

```sh
docker compose run --rm web rake erd
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.sim-form {
display: flex;
gap: 16px;
align-items: flex-end;
margin-bottom: 20px;
flex-wrap: wrap;
}

.form-group {
display: flex;
flex-direction: column;
}

.form-control {
padding: 6px 10px;
font-size: 14px;
}

.btn {
padding: 8px 16px;
background-color: #0070f3;
color: #fff;
border: none;
cursor: pointer;
border-radius: 6px;
}

.btn:hover {
background-color: #005bb5;
}

.result-table {
width: 100%;
border-collapse: collapse;
}

.result-table th,
.result-table td {
padding: 10px;
border-bottom: 1px solid #ddd;
text-align: left;
}

.result-table tr:nth-child(even) {
background-color: #f9f9f9;
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
class ApplicationController < ActionController::API
class ApplicationController < ActionController::Base
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
class PlansController < ApplicationController
PERMITTED_AMPERES = [10, 15, 20, 30, 40, 50, 60].freeze

def index; end

# return json : [{ provider_name: ‘Looopでんき’, plan_name: ‘おうちプラン’, price: ‘1234’ }, …]
def prices
validate_prices_params

ampere = params[:ampere].to_i
usage = params[:usage].to_i
hash = Plan.plan_prices(ampere:, usage:)
render json: hash, status: :ok
rescue StandardError => e
render json: { error: e.message }, status: :bad_request
end

private

def validate_prices_params
ampere = params[:ampere]
usage = params[:usage]

unless ampere.present? && usage.present?
raise ArgumentError, 'Ampere and usage must be provided'
end

# 契約アンペア数 : PERMITTED_AMPERES のいずれかとする(単位A)
unless ampere.match?(/\A\d+\z/) && PERMITTED_AMPERES.include?(ampere.to_i)
raise ArgumentError, "Ampere must be one of #{PERMITTED_AMPERES.join(', ')}"
end

# 使用量 : 0以上の整数(単位kWh)
unless usage.match?(/\A\d+\z/) && usage.to_i >= 0
raise ArgumentError, 'Usage must be a non-negative integer'
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "controllers"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Application } from "@hotwired/stimulus"

const application = Application.start()

// Configure Stimulus development experience
application.debug = false
window.Stimulus = application

export { application }
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Import and register all your controllers from the importmap via controllers/**/*_controller
import { application } from "controllers/application"
import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
eagerLoadControllersFrom("controllers", application)
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
static targets = ["ampere", "usage", "results"]

async search(event) {
event.preventDefault();

const ampere = this.ampereTarget.value;
const usage = this.usageTarget.value;
this.resultsTarget.innerHTML = "";

try {
const response = await fetch(`/plans/prices?ampere=${ampere}&usage=${usage}`);
if (!response.ok) throw new Error("API request failed");
const data = await response.json();
if (Array.isArray(data) && data.length > 0) {
data.forEach(plan => {
const row = this.buildRow(plan);
this.resultsTarget.appendChild(row);
});
} else {
alert("該当するプランがありません。");
}
} catch (error) {
alert("検索に失敗しました: " + error.message);
}
}

buildRow(plan) {
const row = document.createElement("tr");
row.innerHTML = `
<td>${plan.provider_name}</td>
<td>${plan.plan_name}</td>
<td>${plan.price}</td>
`;
return row;
}
}
Loading