Skip to content

Commit

Permalink
Refactor editable attributes (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-isler authored Nov 15, 2024
1 parent 561ee17 commit 46ba198
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 53 deletions.
2 changes: 1 addition & 1 deletion app/controllers/hotsheet/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def broadcast_params
end

def model_params
params.require(model.name.underscore).permit(*model.editable_attributes)
params.require(model.name.underscore).permit(*Hotsheet.editable_attributes_for(model: model))
end

def model
Expand Down
4 changes: 2 additions & 2 deletions app/views/hotsheet/pages/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
<table>
<thead>
<tr>
<% @model.editable_attributes.each do |attribute| %>
<% Hotsheet.editable_attributes_for(model: @model).each do |attribute| %>
<th><%= attribute %></th>
<% end %>
</tr>
</thead>
<tbody>
<% @records.each do |record| %>
<tr>
<% @model.editable_attributes.each do |attribute| %>
<% Hotsheet.editable_attributes_for(model: @model).each do |attribute| %>
<td>
<%= render "editable_attribute", model: @model, record: record, attribute: attribute %>
</td>
Expand Down
43 changes: 0 additions & 43 deletions config/initializers/hotsheet/editable_attributes.rb

This file was deleted.

1 change: 1 addition & 0 deletions lib/hotsheet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
require "hotsheet/engine"
require "hotsheet/version"
require "hotsheet/configuration"
require "hotsheet/editable_attributes"

module Hotsheet
class Error < StandardError; end
Expand Down
9 changes: 4 additions & 5 deletions lib/hotsheet/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def initialize

def model(name)
model_config = ModelConfig.new(name).tap do |config|
yield(config)
yield(config) if block_given?
Rails.application.config.to_prepare { config.validate! }
end
models[name.to_s] = model_config
Expand All @@ -23,12 +23,11 @@ class ModelConfig

def initialize(model_name)
@model_name = model_name
@included_attributes = []
@excluded_attributes = []
end

def validate!
return unless ActiveRecord::Base.connection.table_exists?(model_class.table_name)
return if included_attributes.nil? && excluded_attributes.nil?

ensure_only_one_attribute_set
validate_attribute_existence
Expand All @@ -37,15 +36,15 @@ def validate!
private

def ensure_only_one_attribute_set
return unless included_attributes.any? && excluded_attributes.any?
return if included_attributes.blank? || excluded_attributes.blank?

raise "Can only specify either included or excluded attributes for '#{model_name}'"
end

def validate_attribute_existence
all_attributes = model_class.column_names

(included_attributes + excluded_attributes).each do |attr|
[included_attributes, excluded_attributes].flatten.compact.each do |attr|
unless all_attributes.include?(attr.to_s)
raise "Attribute '#{attr}' doesn't exist on model '#{model_name}'"
end
Expand Down
24 changes: 24 additions & 0 deletions lib/hotsheet/editable_attributes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# frozen_string_literal: true

module Hotsheet
class << self
def editable_attributes_for(model:)
@editable_attributes_for ||= {}
@editable_attributes_for[model] ||= fetch_editable_attributes(model)
end

private

def fetch_editable_attributes(model)
model_config = Hotsheet.configuration.models[model.to_s]

if model_config&.included_attributes
model_config.included_attributes.map(&:to_s)
elsif model_config&.excluded_attributes
model.column_names - model_config.excluded_attributes.map(&:to_s)
else
model.column_names
end
end
end
end
2 changes: 1 addition & 1 deletion spec/dummy/config/initializers/hotsheet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
end

config.model :TableNameTest do |model|
model.included_attributes = []
model.included_attributes = %i[]
end

config.model :VeryLongModelNameForOverflowTest do
Expand Down
82 changes: 82 additions & 0 deletions spec/lib/editable_attributes_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# frozen_string_literal: true

require "spec_helper"

RSpec.describe "Hotsheet" do
describe ".editable_attributes_for" do
subject(:editable_attributes) { Hotsheet.editable_attributes_for(model: Author) }

before do
Hotsheet.instance_variable_set(:@editable_attributes_for, nil) # reset the memoized editable attributes
end

context "when included attributes are specified" do
before do
Hotsheet.configure do |config|
config.model :Author do |model|
model.included_attributes = %i[name birthdate]
end
end
end

it "returns only the included attributes" do
expect(editable_attributes).to eq %w[name birthdate]
end
end

context "when excluded attributes are specified" do
before do
Hotsheet.configure do |config|
config.model :Author do |model|
model.excluded_attributes = %i[gender created_at updated_at]
end
end
end

it "returns all attributes except the excluded ones" do
expect(editable_attributes).to eq %w[id name birthdate]
end
end

context "when included attributes are empty" do
before do
Hotsheet.configure do |config|
config.model :Author do |model|
model.included_attributes = %i[]
end
end
end

it "returns an empty list" do
expect(editable_attributes).to eq %w[]
end
end

context "when excluded attributes are empty" do
before do
Hotsheet.configure do |config|
config.model :Author do |model|
model.excluded_attributes = %i[]
end
end
end

it "returns all attributes" do
expect(editable_attributes).to eq Author.column_names
end
end

context "when no included or excluded attributes are specified" do
before do
Hotsheet.configure do |config|
config.model :Author
end
end

it "returns all attributes of the model" do
expect(Hotsheet.configuration.models["Author"]).to be_a Hotsheet::Configuration::ModelConfig
expect(editable_attributes).to eq %w[id name birthdate gender created_at updated_at]
end
end
end
end
5 changes: 4 additions & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
require "rspec/rails"
require "selenium-webdriver"

require "support/capybara_utils"

%i[firefox firefox_headless].each do |driver|
Capybara.register_driver driver do |app|
args = ["--headless"] if driver == :firefox_headless
Expand All @@ -23,7 +25,8 @@
RSpec.configure do |config|
Kernel.srand config.seed

config.include Capybara::DSL
config.include Capybara::DSL, type: :system
config.include CapybaraUtils, type: :system

config.disable_monkey_patching!
config.filter_rails_from_backtrace!
Expand Down
9 changes: 9 additions & 0 deletions spec/support/capybara_utils.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module CapybaraUtils
def wait_for_turbo(timeout = nil)
return unless has_css?(".turbo-progress-bar", visible: true, wait: 1.second)

has_no_css?(".turbo-progress-bar", wait: timeout.presence || 5.seconds)
end
end
8 changes: 8 additions & 0 deletions spec/system/editable_attributes_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,16 @@

describe "update strings" do
before do
Hotsheet.configure do |config|
config.model :Author do |model|
model.included_attributes = %i[name birthdate]
end
end
Hotsheet.instance_variable_set(:@editable_attributes_for, nil) # reset the memoized editable attributes

visit "/hotsheet"
click_link "Author"

find(".readonly-attribute", text: "Stephen").click
fill_in "author_name", with: "King"
end
Expand Down

0 comments on commit 46ba198

Please sign in to comment.