diff --git a/.rubocop.yml b/.rubocop.yml index ef372c1..afac4b6 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -10,6 +10,7 @@ plugins: AllCops: Exclude: - bin/* + - extra/**/* - spec/dummy_rails/**/* - vendor/**/* NewCops: enable diff --git a/extra/sample_features_app/admin/items.rb b/extra/sample_features_app/admin/items.rb index 190a1a0..70a8322 100644 --- a/extra/sample_features_app/admin/items.rb +++ b/extra/sample_features_app/admin/items.rb @@ -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 @@ -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 diff --git a/lib/tiny_admin/actions/index.rb b/lib/tiny_admin/actions/index.rb index eb1e796..fd62a77 100644 --- a/lib/tiny_admin/actions/index.rb +++ b/lib/tiny_admin/actions/index.rb @@ -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 diff --git a/lib/tiny_admin/plugins/base_repository.rb b/lib/tiny_admin/plugins/base_repository.rb index ee320da..4e2ffb0 100644 --- a/lib/tiny_admin/plugins/base_repository.rb +++ b/lib/tiny_admin/plugins/base_repository.rb @@ -3,7 +3,8 @@ module TinyAdmin module Plugins class BaseRepository - RecordNotFound = Class.new(StandardError) + class RecordNotFound < StandardError + end attr_reader :model diff --git a/lib/tiny_admin/plugins/no_auth.rb b/lib/tiny_admin/plugins/no_auth.rb index 8c8f237..e840a97 100644 --- a/lib/tiny_admin/plugins/no_auth.rb +++ b/lib/tiny_admin/plugins/no_auth.rb @@ -8,7 +8,7 @@ def configure(_app, _opts = {}); end end module InstanceMethods - def authenticate_user! + def authenticate_user! # rubocop:disable Naming/PredicateMethod true end diff --git a/lib/tiny_admin/views/components/pagination.rb b/lib/tiny_admin/views/components/pagination.rb index ec7e0a8..d40ed0d 100644 --- a/lib/tiny_admin/views/components/pagination.rb +++ b/lib/tiny_admin/views/components/pagination.rb @@ -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 } diff --git a/spec/lib/tiny_admin/actions/basic_action_spec.rb b/spec/lib/tiny_admin/actions/basic_action_spec.rb index 19774cd..eab60dd 100644 --- a/spec/lib/tiny_admin/actions/basic_action_spec.rb +++ b/spec/lib/tiny_admin/actions/basic_action_spec.rb @@ -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 diff --git a/spec/lib/tiny_admin/field_spec.rb b/spec/lib/tiny_admin/field_spec.rb index a7eac69..90bd626 100644 --- a/spec/lib/tiny_admin/field_spec.rb +++ b/spec/lib/tiny_admin/field_spec.rb @@ -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 @@ -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 @@ -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 @@ -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 @@ -81,7 +81,7 @@ 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 @@ -89,7 +89,7 @@ def self.upcase(value, options: []) 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) diff --git a/spec/lib/tiny_admin/plugins/active_record_repository_spec.rb b/spec/lib/tiny_admin/plugins/active_record_repository_spec.rb index 93e4d5e..9c6db36 100644 --- a/spec/lib/tiny_admin/plugins/active_record_repository_spec.rb +++ b/spec/lib/tiny_admin/plugins/active_record_repository_spec.rb @@ -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 @@ -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 @@ -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 @@ -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") @@ -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) @@ -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 diff --git a/spec/lib/tiny_admin/route_for_spec.rb b/spec/lib/tiny_admin/route_for_spec.rb index c8f63d5..75e5bed 100644 --- a/spec/lib/tiny_admin/route_for_spec.rb +++ b/spec/lib/tiny_admin/route_for_spec.rb @@ -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 diff --git a/spec/lib/tiny_admin/section_spec.rb b/spec/lib/tiny_admin/section_spec.rb index cdff959..196b07e 100644 --- a/spec/lib/tiny_admin/section_spec.rb +++ b/spec/lib/tiny_admin/section_spec.rb @@ -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 diff --git a/spec/lib/tiny_admin/settings_spec.rb b/spec/lib/tiny_admin/settings_spec.rb index 0c8fe5e..3ad98ef 100644 --- a/spec/lib/tiny_admin/settings_spec.rb +++ b/spec/lib/tiny_admin/settings_spec.rb @@ -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 diff --git a/spec/lib/tiny_admin/store_spec.rb b/spec/lib/tiny_admin/store_spec.rb index d1c5b4b..4aa2a39 100644 --- a/spec/lib/tiny_admin/store_spec.rb +++ b/spec/lib/tiny_admin/store_spec.rb @@ -23,7 +23,7 @@ describe "#prepare_sections" do context "with a content section" do let(:sections) do - [{slug: "about", name: "About", type: :content, content: "

About

"}] + [{ slug: "about", name: "About", type: :content, content: "

About

" }] end it "adds to pages and navbar", :aggregate_failures do @@ -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 @@ -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 @@ -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 @@ -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 @@ -105,7 +105,7 @@ let(:section_module) do mod = Class.new do def self.to_h - {slug: "dynamic", name: "Dynamic", type: :content, content: "

Hi

"} + { slug: "dynamic", name: "Dynamic", type: :content, content: "

Hi

" } end end mod @@ -143,9 +143,9 @@ def self.to_h context "with multiple section types" do let(:sections) do [ - {slug: "about", name: "About", type: :content, content: "

Test

"}, - {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: "

Test

" }, + { slug: "users", name: "Users", type: :resource, model: Author }, + { slug: "ext", name: "External", type: :url, url: "https://example.com" } ] end diff --git a/spec/lib/tiny_admin/utils_spec.rb b/spec/lib/tiny_admin/utils_spec.rb index 0b74d3a..7dc4743 100644 --- a/spec/lib/tiny_admin/utils_spec.rb +++ b/spec/lib/tiny_admin/utils_spec.rb @@ -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 @@ -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 diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 5bac978..2dcee3b 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -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 diff --git a/tiny_admin.gemspec b/tiny_admin.gemspec index 950727e..296de00 100644 --- a/tiny_admin.gemspec +++ b/tiny_admin.gemspec @@ -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