Skip to content

Commit 426d95a

Browse files
committed
Refactor config
1 parent e02079b commit 426d95a

File tree

28 files changed

+239
-246
lines changed

28 files changed

+239
-246
lines changed

.rubocop.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ AllCops:
77
Exclude:
88
- gemfiles/**/*
99
- spec/dummy/db/schema.rb
10+
- spec/dummy/tmp/**/*
1011

1112
Style/ClassAndModuleChildren:
1213
Enabled: false

app/controllers/hotsheet/sheets_controller.rb

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,19 @@
33
class Hotsheet::SheetsController < Hotsheet::ApplicationController
44
before_action :set_sheet
55
before_action :set_column, only: :update
6+
before_action :set_resource, only: :update
67

78
def index
89
@columns = @sheet.columns
9-
@cells = @sheet.cells_for(@columns)
10+
@cells = @sheet.cells_for @columns
1011
end
1112

1213
def update
13-
resource = @sheet.model.find_by(id: params[:id])
14-
return respond t("hotsheet.errors.not_found") if resource.nil?
15-
return respond if resource.update @column.name => params[:value]
16-
17-
respond resource.errors.full_messages.first
14+
if @resource.update params[:column_name] => params[:value]
15+
respond
16+
else
17+
respond @resource.errors.full_messages.first
18+
end
1819
end
1920

2021
def error
@@ -28,10 +29,16 @@ def set_sheet
2829
end
2930

3031
def set_column
31-
@column = @sheet.columns.find { |column| column.name == params[:column_name] }
32-
return respond t("hotsheet.errors.not_found") if @column.nil?
32+
@column = @sheet.columns[params[:column_name]]
33+
return respond Hotsheet.t "errors.not_found", "Not found" if @column.nil?
34+
35+
respond Hotsheet.t "errors.forbidden", "Forbidden" unless @column.editable?
36+
end
37+
38+
def set_resource
39+
@resource = @sheet.model.find_by id: params[:id]
3340

34-
respond t("hotsheet.errors.forbidden") unless @column.editable?
41+
respond Hotsheet.t "errors.not_found", "Not found" if @resource.nil?
3542
end
3643

3744
def respond(message = "")

app/views/hotsheet/shared/_flash.html.erb

Lines changed: 0 additions & 5 deletions
This file was deleted.

app/views/hotsheet/shared/_nav.html.erb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
<nav class="nav" data-controller="nav">
22
<ul>
3-
<li><%= link_to t("hotsheet.title"), root_path, class: "title" %></li>
3+
<li><%= link_to Hotsheet.t("title", "Hotsheet"), root_path, class: "title" %></li>
44
</ul>
55
<ul class="sheets">
6-
<% Hotsheet.sheets.each_with_index do |sheet, index| %>
7-
<% sheet_name, model = sheet %>
6+
<% Hotsheet.sheets.each_with_index do |entry, index| %>
87
<li>
9-
<%= link_to model.human_name, sheet_path_for(sheet_name),
8+
<% sheet_name, sheet = entry %>
9+
<%= link_to sheet.model.model_name.human(count: 2), sheet_path_for(sheet_name),
1010
class: ("active" if params[:sheet_name] == sheet_name), data: { x: index } %>
1111
</li>
1212
<% end %>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<h1><%= t "hotsheet.not_found" %></h1>
1+
<h1><%= Hotsheet.t "errors.not_found", "404: Not found" %></h1>

app/views/hotsheet/sheets/index.html.erb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
<div class="table" spellcheck="false" data-controller="sheets">
2-
<% @cells.each_with_index do |values, x_index| %>
3-
<% column = @columns[x_index] %>
2+
<% @columns.each_with_index do |entry, x_index| %>
3+
<% column_name, column = entry %>
44
<% editable = column.editable? %>
55

66
<div class="column">
7-
<span class="cell header"
8-
data-name="<%= column.name %>"><%= @sheet.model.human_attribute_name column.name %></span>
7+
<span class="cell header" data-name="<%= column_name %>">
8+
<%= @sheet.model.human_attribute_name column_name %>
9+
</span>
910

10-
<% values.each_with_index do |value, y_index| %>
11+
<% @cells[x_index].each_with_index do |value, y_index| %>
1112
<% if editable %>
1213
<span class="cell" tabindex="0" data-xy="<%= "#{x_index},#{y_index}" %>"><%= value %></span>
1314
<% else %>

app/views/layouts/hotsheet/application.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<body>
1616
<%= render "hotsheet/shared/nav" %>
1717
<main>
18-
<%= render "hotsheet/shared/flash" %>
18+
<div class="flash"></div>
1919
<%= yield %>
2020
</main>
2121
</body>

bin/setup

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ system! "bun i"
1313
system! "bundle"
1414
system! "bundle exec appraisal install"
1515

16-
puts "---- Bundling assets ----"
17-
system! "bun run build"
18-
1916
puts "---- Setting up database ----"
2017
system! "bundle exec rails db:reset db:schema:load"
2118
system! "RAILS_ENV=development bundle exec rails db:seed"

config/locales/en.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@ en:
33
errors:
44
forbidden: Forbidden
55
not_found: Not found
6-
not_found: 404 Not Found
76
title: Hotsheet

config/routes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
next if Rails::VERSION::MAJOR < 8 && !defined? Rails::Server
55

66
Hotsheet.sheets.each_key do |sheet_name|
7-
resources sheet_name, only: %i[index update], controller: :sheets, sheet_name: sheet_name
7+
resources sheet_name, sheet_name:, controller: :sheets, only: %i[index update]
88
end
99

1010
root "sheets#root"

lib/hotsheet.rb

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,51 @@
11
# frozen_string_literal: true
22

3+
require "hotsheet/version"
4+
require "hotsheet/engine"
5+
require "hotsheet/config"
6+
require "hotsheet/sheet"
7+
require "hotsheet/column"
8+
39
module Hotsheet
410
class Error < StandardError; end
511

612
class << self
7-
def configure(&config)
8-
@config = config
13+
include Config
14+
15+
CONFIG = {}.freeze
16+
17+
attr_reader :config
18+
19+
def configure(config = {}, &sheets)
20+
@config = [merge_config!(CONFIG, config), sheets]
21+
self
922
end
1023

1124
def sheets
12-
@sheets ||= Config.new.tap { |c| c.instance_eval(&@config) }.sheets
25+
@sheets ||= begin
26+
@sheets = {}
27+
instance_eval(&@config.pop)
28+
@sheets
29+
end
30+
end
31+
32+
def t(key, default)
33+
I18n.t key, scope: "hotsheet", default:
34+
end
35+
36+
private
37+
38+
def sheet(name, config = {}, &)
39+
ensure_sheet_exists! name
40+
41+
sheet = Sheet.new(name, config, &)
42+
@sheets[sheet.model.table_name] = sheet
43+
end
44+
45+
def ensure_sheet_exists!(name)
46+
return if Object.const_defined? name
47+
48+
raise Hotsheet::Error, "Unknown model '#{name}'"
1349
end
1450
end
1551
end
16-
17-
require "hotsheet/config"
18-
require "hotsheet/engine"
19-
require "hotsheet/sheet"
20-
require "hotsheet/sheet/column"
21-
require "hotsheet/version"

lib/hotsheet/column.rb

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
class Hotsheet::Column
4+
include Hotsheet::Config
5+
6+
attr_reader :config
7+
8+
CONFIG = {
9+
editable: { allowed_classes: [FalseClass, Proc], default: true },
10+
visible: { allowed_classes: [FalseClass, Proc], default: true }
11+
}.freeze
12+
13+
def initialize(config)
14+
@config = merge_config! CONFIG, config
15+
end
16+
17+
def editable?
18+
is? :editable
19+
end
20+
21+
def visible?
22+
is? :visible
23+
end
24+
25+
private
26+
27+
def is?(permission)
28+
perm = @config[permission]
29+
perm.is_a?(Proc) ? perm.call : perm
30+
end
31+
end

lib/hotsheet/config.rb

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
# frozen_string_literal: true
22

3-
class Hotsheet::Config
4-
attr_reader :sheets
3+
module Hotsheet::Config
4+
def merge_config!(default, custom)
5+
config = default.transform_values { |value| value[:default] }
56

6-
def initialize
7-
@sheets = {}
8-
end
7+
custom.each do |key, value|
8+
unless default.key? key
9+
raise Hotsheet::Error, "Config must be one of #{default.keys}, got '#{key}'"
10+
end
911

10-
def sheet(name, config = {}, &columns)
11-
sheet = Hotsheet::Sheet.new(name, config).tap do |s|
12-
s.column :id, editable: false
13-
columns ? s.instance_eval(&columns) : s.use_default_configuration
12+
ensure_allowed_value! key, value, default[key]
13+
config[key] = value
1414
end
1515

16-
@sheets[sheet.model.table_name] = sheet
16+
config
17+
end
18+
19+
private
20+
21+
def ensure_allowed_value!(key, value, config)
22+
allowed = config[:allowed_classes]
23+
value = value.class
24+
25+
return if allowed.include? value
26+
27+
raise Hotsheet::Error, "Config '#{key}' must be one of #{allowed}, got '#{value}'"
1728
end
1829
end

lib/hotsheet/engine.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@
22

33
class Hotsheet::Engine < Rails::Engine
44
isolate_namespace Hotsheet
5+
6+
if config.respond_to? :assets
7+
config.assets.paths << Hotsheet::Engine.root.join("app/assets")
8+
end
59
end

lib/hotsheet/sheet.rb

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,44 @@
11
# frozen_string_literal: true
22

33
class Hotsheet::Sheet
4-
attr_accessor :model
4+
include Hotsheet::Config
55

6-
def initialize(name, config = {})
7-
ensure_model_exists! name
6+
CONFIG = {}.freeze
87

9-
@config = config
10-
@model = name.to_s.constantize
11-
@columns = []
12-
end
8+
attr_reader :config, :model
139

14-
def use_default_configuration
15-
@model.column_names[1..].each { |name| column name }
16-
end
17-
18-
def human_name
19-
@model.model_name.human count: 2
20-
end
21-
22-
def column(name, config = {})
23-
ensure_column_exists! name
10+
def initialize(name, config, &columns)
11+
@config = merge_config! CONFIG, config
12+
@model = name.to_s.constantize
13+
@columns = {}
2414

25-
@columns << Column.new(name, config)
15+
column :id, editable: false
16+
columns ? instance_eval(&columns) : use_default_configuration
2617
end
2718

2819
def columns
29-
@columns.select(&:visible?)
20+
@columns.select { |_name, column| column.visible? }
3021
end
3122

3223
def cells_for(columns)
33-
@model.pluck(*columns.map(&:name)).transpose
24+
@model.pluck(*columns.keys).transpose
3425
end
3526

3627
private
3728

38-
def ensure_model_exists!(name)
39-
return if Object.const_defined? name
29+
def use_default_configuration
30+
@model.column_names[1..].each { |name| column name }
31+
end
32+
33+
def column(name, config = {})
34+
ensure_column_exists! name
4035

41-
raise Hotsheet::Error, "Unknown model '#{name}'"
36+
@columns[name.to_s] = Hotsheet::Column.new config
4237
end
4338

4439
def ensure_column_exists!(name)
4540
return if @model.column_names.include? name.to_s
4641

47-
raise Hotsheet::Error, "Unknown column '#{name}' for '#{@model.table_name}'"
42+
raise Hotsheet::Error, "Column must be one of #{@model.column_names}, got '#{name}'"
4843
end
4944
end

lib/hotsheet/sheet/column.rb

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)