Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ plugins:
AllCops:
Exclude:
- bin/*
- extra/**/*
- spec/dummy_rails/**/*
- vendor/**/*
NewCops: enable
Expand Down
6 changes: 3 additions & 3 deletions extra/sample_features_app/admin/items.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ module Admin

class ItemsRepo < ::TinyAdmin::Plugins::BaseRepository
def fields(options: nil)
COLUMNS.each_with_object({}) do |name, result|
result[name] = TinyAdmin::Field.create_field(name: name)
COLUMNS.to_h do |name|
[name, TinyAdmin::Field.create_field(name: name)]
end
end

Expand All @@ -28,7 +28,7 @@ def index_title
def list(page: 1, limit: 10, filters: nil, sort: ['id'])
page_offset = page.positive? ? (page - 1) * limit : 0
[
RECORDS[page_offset...page_offset + limit],
RECORDS[page_offset...(page_offset + limit)],
RECORDS.size
]
end
Expand Down
4 changes: 2 additions & 2 deletions lib/tiny_admin/actions/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ def evaluate_options(options)

def prepare_filters(fields)
filters = (options[:filters] || []).map { _1.is_a?(Hash) ? _1 : { field: _1 } }
filters = filters.each_with_object({}) { |filter, result| result[filter[:field]] = filter }
values = (params['q'] || {})
filters = filters.to_h { |filter| [filter[:field], filter] }
values = params['q'] || {}
fields.each_with_object({}) do |(name, field), result|
result[field] = { value: values[name], filter: filters[name] } if filters.key?(name)
end
Expand Down
3 changes: 2 additions & 1 deletion lib/tiny_admin/plugins/base_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
module TinyAdmin
module Plugins
class BaseRepository
RecordNotFound = Class.new(StandardError)
class RecordNotFound < StandardError
end

attr_reader :model

Expand Down
2 changes: 1 addition & 1 deletion lib/tiny_admin/plugins/no_auth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def configure(_app, _opts = {}); end
end

module InstanceMethods
def authenticate_user!
def authenticate_user! # rubocop:disable Naming/PredicateMethod
true
end

Expand Down
2 changes: 1 addition & 1 deletion lib/tiny_admin/views/components/pagination.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def view_template
pages_range((current > pages - 4 ? current - 2 : pages - 2)..pages)
else
pages_range(1..1, with_dots: true)
pages_range(current - 2..current + 2, with_dots: true)
pages_range((current - 2)..(current + 2), with_dots: true)
pages_range(pages..pages)
end
}
Expand Down
27 changes: 14 additions & 13 deletions spec/lib/tiny_admin/actions/basic_action_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,36 @@
it "handles simple string field names" do
result = action.attribute_options(["id", "name"])
expect(result).to eq(
"id" => {field: "id"},
"name" => {field: "name"}
"id" => { field: "id" },
"name" => { field: "name" }
)
end

it "handles single-entry hash with method shorthand" do
result = action.attribute_options([{title: "downcase, capitalize"}])
result = action.attribute_options([{ title: "downcase, capitalize" }])
expect(result).to eq(
"title" => {field: "title", method: "downcase, capitalize"}
"title" => { field: "title", method: "downcase, capitalize" }
)
end

it "handles multi-entry hash with explicit field key" do
result = action.attribute_options([{field: "author_id", link_to: "authors"}])
result = action.attribute_options([{ field: "author_id", link_to: "authors" }])
expect(result).to eq(
"author_id" => {field: "author_id", link_to: "authors"}
"author_id" => { field: "author_id", link_to: "authors" }
)
end

it "handles mixed input types" do
result = action.attribute_options([
opts = [
"id",
{title: "upcase"},
{field: "created_at", method: "strftime, %Y-%m-%d"}
])
{ title: "upcase" },
{ field: "created_at", method: "strftime, %Y-%m-%d" }
]
result = action.attribute_options(opts)
expect(result).to eq(
"id" => {field: "id"},
"title" => {field: "title", method: "upcase"},
"created_at" => {field: "created_at", method: "strftime, %Y-%m-%d"}
"id" => { field: "id" },
"title" => { field: "title", method: "upcase" },
"created_at" => { field: "created_at", method: "strftime, %Y-%m-%d" }
)
end
end
Expand Down
12 changes: 6 additions & 6 deletions spec/lib/tiny_admin/field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
end

it "uses the provided options when given" do
options = {method: "downcase"}
options = { method: "downcase" }
field = described_class.create_field(name: "name", options: options)
expect(field.options).to eq(options)
end
Expand All @@ -39,7 +39,7 @@

describe "#apply_call_option" do
it "chains method calls on the target" do
field = described_class.new(name: "title", title: "Title", type: :string, options: {call: "to_s, downcase"})
field = described_class.new(name: "title", title: "Title", type: :string, options: { call: "to_s, downcase" })
expect(field.apply_call_option(42)).to eq("42")
end

Expand All @@ -49,7 +49,7 @@
end

it "handles nil target safely via safe navigation" do
field = described_class.new(name: "title", title: "Title", type: :string, options: {call: "nonexistent"})
field = described_class.new(name: "title", title: "Title", type: :string, options: { call: "nonexistent" })
expect(field.apply_call_option(nil)).to be_nil
end
end
Expand All @@ -66,7 +66,7 @@
end

it "applies the helper method from options" do
field = described_class.new(name: "name", title: "Name", type: :string, options: {method: "downcase"})
field = described_class.new(name: "name", title: "Name", type: :string, options: { method: "downcase" })
allow(TinyAdmin.settings).to receive(:helper_class).and_return(TinyAdmin::Support)
expect(field.translate_value("HELLO")).to eq("hello")
end
Expand All @@ -81,15 +81,15 @@ def self.upcase(value, options: [])

field = described_class.new(
name: "name", title: "Name", type: :string,
options: {method: "upcase", converter: "TestConverter"}
options: { method: "upcase", converter: "TestConverter" }
)
expect(field.translate_value("hello")).to eq("HELLO")
end

it "passes additional args to the method" do
field = described_class.new(
name: "value", title: "Value", type: :float,
options: {method: "round, 1"}
options: { method: "round, 1" }
)
allow(TinyAdmin.settings).to receive(:helper_class).and_return(TinyAdmin::Support)
expect(field.translate_value(3.456)).to eq(3.5)
Expand Down
14 changes: 7 additions & 7 deletions spec/lib/tiny_admin/plugins/active_record_repository_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
end

it "returns only specified fields when options given" do
options = {"name" => {}, "email" => {}}
options = { "name" => {}, "email" => {} }
fields = repository.fields(options: options)
expect(fields.keys).to eq(["name", "email"])
end
Expand Down Expand Up @@ -72,7 +72,7 @@
end

it "returns only specified fields when fields given", :aggregate_failures do
attrs = repository.index_record_attrs(author, fields: {"name" => nil, "email" => nil})
attrs = repository.index_record_attrs(author, fields: { "name" => nil, "email" => nil })
expect(attrs.keys).to eq(["name", "email"])
expect(attrs["name"]).to eq(author.name)
end
Expand All @@ -93,7 +93,7 @@
end

it "sorts when sort option given" do
records, = repository.list(page: 1, limit: 10, sort: {name: :desc})
records, = repository.list(page: 1, limit: 10, sort: { name: :desc })
names = records.map(&:name)
expect(names).to eq(names.sort.reverse)
end
Expand All @@ -104,7 +104,7 @@

it "filters string fields with LIKE" do
title_field = TinyAdmin::Field.new(name: "title", title: "Title", type: :string)
filters = {title_field => {value: "post 1"}}
filters = { title_field => { value: "post 1" } }
results = post_repository.apply_filters(Post.all, filters)
results.each do |post|
expect(post.title.downcase).to include("post 1")
Expand All @@ -114,7 +114,7 @@
it "filters non-string fields with equality" do
author = Author.first
author_field = TinyAdmin::Field.new(name: "author_id", title: "Author", type: :integer)
filters = {author_field => {value: author.id}}
filters = { author_field => { value: author.id } }
results = post_repository.apply_filters(Post.all, filters)
results.each do |post|
expect(post.author_id).to eq(author.id)
Expand All @@ -123,14 +123,14 @@

it "skips filters with nil or empty values" do
title_field = TinyAdmin::Field.new(name: "title", title: "Title", type: :string)
filters = {title_field => {value: nil}}
filters = { title_field => { value: nil } }
results = post_repository.apply_filters(Post.all, filters)
expect(results.count).to eq(Post.count)
end

it "sanitizes SQL LIKE input" do
title_field = TinyAdmin::Field.new(name: "title", title: "Title", type: :string)
filters = {title_field => {value: "100%"}}
filters = { title_field => { value: "100%" } }
# Should not raise or cause SQL injection
expect { post_repository.apply_filters(Post.all, filters).to_a }.not_to raise_error
end
Expand Down
2 changes: 1 addition & 1 deletion spec/lib/tiny_admin/route_for_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

RSpec.describe "TinyAdmin.route_for" do
RSpec.describe "TinyAdmin.route_for" do # rubocop:disable RSpec/DescribeClass
before do
allow(TinyAdmin.settings).to receive(:root_path).and_return("/admin")
end
Expand Down
4 changes: 2 additions & 2 deletions spec/lib/tiny_admin/section_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
end

it "stores provided options" do
section = described_class.new(name: "Link", slug: "link", options: {target: "_blank"})
expect(section.options).to eq({target: "_blank"})
section = described_class.new(name: "Link", slug: "link", options: { target: "_blank" })
expect(section.options).to eq({ target: "_blank" })
end
end
end
2 changes: 1 addition & 1 deletion spec/lib/tiny_admin/settings_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
end

it "converts nested string class names to constants" do
settings[:authentication] = {plugin: "TinyAdmin::Plugins::NoAuth"}
settings[:authentication] = { plugin: "TinyAdmin::Plugins::NoAuth" }
expect(settings[:authentication, :plugin]).to eq(TinyAdmin::Plugins::NoAuth)
end

Expand Down
20 changes: 10 additions & 10 deletions spec/lib/tiny_admin/store_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
describe "#prepare_sections" do
context "with a content section" do
let(:sections) do
[{slug: "about", name: "About", type: :content, content: "<h1>About</h1>"}]
[{ slug: "about", name: "About", type: :content, content: "<h1>About</h1>" }]
end

it "adds to pages and navbar", :aggregate_failures do
Expand All @@ -42,7 +42,7 @@
end

let(:sections) do
[{slug: "dashboard", name: "Dashboard", type: :page, page: page_class}]
[{ slug: "dashboard", name: "Dashboard", type: :page, page: page_class }]
end

it "adds to pages and navbar", :aggregate_failures do
Expand All @@ -56,7 +56,7 @@

context "with a resource section" do
let(:sections) do
[{slug: "authors", name: "Authors", type: :resource, model: Author}]
[{ slug: "authors", name: "Authors", type: :resource, model: Author }]
end

it "adds to resources and navbar", :aggregate_failures do
Expand All @@ -71,7 +71,7 @@

context "with a hidden resource section" do
let(:sections) do
[{slug: "secret", name: "Secret", type: :resource, model: Author, options: [:hidden]}]
[{ slug: "secret", name: "Secret", type: :resource, model: Author, options: [:hidden] }]
end

it "adds to resources but not to visible navbar items", :aggregate_failures do
Expand All @@ -84,14 +84,14 @@

context "with a url section" do
let(:sections) do
[{slug: "google", name: "Google", type: :url, url: "https://google.com", options: {target: "_blank"}}]
[{ slug: "google", name: "Google", type: :url, url: "https://google.com", options: { target: "_blank" } }]
end

it "adds to navbar with the url as path", :aggregate_failures do
store.prepare_sections(sections, logout: nil)
expect(store.navbar.size).to eq(1)
expect(store.navbar.first.path).to eq("https://google.com")
expect(store.navbar.first.options).to eq({target: "_blank"})
expect(store.navbar.first.options).to eq({ target: "_blank" })
end

it "does not add to pages or resources", :aggregate_failures do
Expand All @@ -105,7 +105,7 @@
let(:section_module) do
mod = Class.new do
def self.to_h
{slug: "dynamic", name: "Dynamic", type: :content, content: "<p>Hi</p>"}
{ slug: "dynamic", name: "Dynamic", type: :content, content: "<p>Hi</p>" }
end
end
mod
Expand Down Expand Up @@ -143,9 +143,9 @@ def self.to_h
context "with multiple section types" do
let(:sections) do
[
{slug: "about", name: "About", type: :content, content: "<p>Test</p>"},
{slug: "users", name: "Users", type: :resource, model: Author},
{slug: "ext", name: "External", type: :url, url: "https://example.com"}
{ slug: "about", name: "About", type: :content, content: "<p>Test</p>" },
{ slug: "users", name: "Users", type: :resource, model: Author },
{ slug: "ext", name: "External", type: :url, url: "https://example.com" }
]
end

Expand Down
4 changes: 2 additions & 2 deletions spec/lib/tiny_admin/utils_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
end

it "converts nested hash params to bracket notation", :aggregate_failures do
result = utils_instance.params_to_s("q" => {"title" => "test", "author" => "john"})
result = utils_instance.params_to_s("q" => { "title" => "test", "author" => "john" })
expect(result).to include("q[title]=test")
expect(result).to include("q[author]=john")
end
Expand All @@ -19,7 +19,7 @@
end

it "handles mixed flat and nested params", :aggregate_failures do
result = utils_instance.params_to_s("p" => "1", "q" => {"name" => "test"})
result = utils_instance.params_to_s("p" => "1", "q" => { "name" => "test" })
expect(result).to include("p=1")
expect(result).to include("q[name]=test")
end
Expand Down
2 changes: 1 addition & 1 deletion spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
begin
ActiveRecord::Migration.maintain_test_schema!
rescue ActiveRecord::PendingMigrationError => e
puts e.to_s.strip
puts e.to_s.strip # rubocop:disable RSpec/Output
exit 1
end
end
Expand Down
8 changes: 4 additions & 4 deletions tiny_admin.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ Gem::Specification.new do |spec|
spec.files = Dir['{app,db,lib}/**/*', 'LICENSE.txt', 'README.md']
spec.require_paths = ['lib']

spec.add_runtime_dependency 'phlex', '~> 1', '>= 1.10.0'
spec.add_runtime_dependency 'roda', '~> 3'
spec.add_runtime_dependency 'tilt', '~> 2'
spec.add_runtime_dependency 'zeitwerk', '~> 2'
spec.add_dependency 'phlex', '~> 1', '>= 1.10.0'
spec.add_dependency 'roda', '~> 3'
spec.add_dependency 'tilt', '~> 2'
spec.add_dependency 'zeitwerk', '~> 2'
end
Loading