diff --git a/app/controllers/administrate/application_controller.rb b/app/controllers/administrate/application_controller.rb index f07a01575326ea64c8554e5d2e1d5ea0478ef08f..e81454a92f7af3fb04ea986baf1313249bfcfebd 100644 --- a/app/controllers/administrate/application_controller.rb +++ b/app/controllers/administrate/application_controller.rb @@ -9,7 +9,7 @@ module Administrate search_term).run resources = apply_collection_includes(resources) resources = order.apply(resources) - resources = resources.page(params[:page]).per(records_per_page) + resources = resources.page(params[:_page]).per(records_per_page) page = Administrate::Page::Collection.new(dashboard, order: order) render locals: { @@ -105,10 +105,7 @@ module Administrate end def sorting_attribute - params.fetch(resource_name, {}).fetch( - :order, - default_sorting_attribute, - ) + sorting_params.fetch(:order) { default_sorting_attribute } end def default_sorting_attribute @@ -116,16 +113,17 @@ module Administrate end def sorting_direction - params.fetch(resource_name, {}).fetch( - :direction, - default_sorting_direction, - ) + sorting_params.fetch(:direction) { default_sorting_direction } end def default_sorting_direction nil end + def sorting_params + Hash.try_convert(request.query_parameters[resource_name]) || {} + end + def dashboard @dashboard ||= dashboard_class.new end diff --git a/app/helpers/administrate/application_helper.rb b/app/helpers/administrate/application_helper.rb index 79b9e37eb2d56868242f71baa1ef39843c98ef73..d02ff069d6021d25a8f35bd7950ef4cd80d0f6e5 100644 --- a/app/helpers/administrate/application_helper.rb +++ b/app/helpers/administrate/application_helper.rb @@ -70,11 +70,11 @@ module Administrate association_params = collection_names.map do |assoc_name| { assoc_name => %i[order direction page per_page] } end - params.permit(:search, :id, :page, :per_page, association_params) + params.permit(:search, :id, :_page, :per_page, association_params) end def clear_search_params - params.except(:search, :page).permit( + params.except(:search, :_page).permit( :per_page, resource_name => %i[order direction] ) end diff --git a/app/views/administrate/application/index.html.erb b/app/views/administrate/application/index.html.erb index 80a5ae24c8864ac0491f521353902ff1f0dad4f8..5e1796ef8f4c504b95c1d7ecc10ae427a5233c58 100644 --- a/app/views/administrate/application/index.html.erb +++ b/app/views/administrate/application/index.html.erb @@ -62,5 +62,5 @@ It renders the `_table` partial to display details about the resources. table_title: "page-title" ) %> - <%= paginate resources %> + <%= paginate resources, param_name: '_page' %> </section> diff --git a/spec/example_app/app/controllers/admin/pages_controller.rb b/spec/example_app/app/controllers/admin/pages_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..38e505daba00b26d570045b61d9578b27797d8a2 --- /dev/null +++ b/spec/example_app/app/controllers/admin/pages_controller.rb @@ -0,0 +1,4 @@ +module Admin + class PagesController < Admin::ApplicationController + end +end diff --git a/spec/example_app/app/dashboards/page_dashboard.rb b/spec/example_app/app/dashboards/page_dashboard.rb new file mode 100644 index 0000000000000000000000000000000000000000..049fd0113a238b2ff7be672866c2ce1728d2035e --- /dev/null +++ b/spec/example_app/app/dashboards/page_dashboard.rb @@ -0,0 +1,34 @@ +require "administrate/base_dashboard" + +class PageDashboard < Administrate::BaseDashboard + ATTRIBUTE_TYPES = { + product: Field::BelongsTo, + id: Field::Number, + title: Field::String, + body: Field::Text, + created_at: Field::DateTime, + updated_at: Field::DateTime, + }.freeze + + COLLECTION_ATTRIBUTES = %i[ + id + title + ].freeze + + SHOW_PAGE_ATTRIBUTES = %i[ + product + id + title + body + created_at + updated_at + ].freeze + + FORM_ATTRIBUTES = %i[ + product + title + body + ].freeze + + COLLECTION_FILTERS = {}.freeze +end diff --git a/spec/example_app/app/dashboards/product_dashboard.rb b/spec/example_app/app/dashboards/product_dashboard.rb index bf89c5272be15e40409a655d2f6ad0b5398838f4..9287b65a24ffcfe16048b695de33eb7043243a78 100644 --- a/spec/example_app/app/dashboards/product_dashboard.rb +++ b/spec/example_app/app/dashboards/product_dashboard.rb @@ -3,6 +3,7 @@ require "administrate/base_dashboard" class ProductDashboard < Administrate::BaseDashboard ATTRIBUTES = [ :name, + :pages, :price, :description, :image_url, @@ -16,6 +17,7 @@ class ProductDashboard < Administrate::BaseDashboard description: Field::Text, image_url: Field::Url, name: Field::String, + pages: Field::HasMany, price: Field::Number.with_options(prefix: "$", decimals: 2), product_meta_tag: Field::HasOne, release_year: Field::Select.with_options( diff --git a/spec/example_app/app/models/page.rb b/spec/example_app/app/models/page.rb new file mode 100644 index 0000000000000000000000000000000000000000..a4a3058aa9d61e8fecac662767e6c2c1dd01c851 --- /dev/null +++ b/spec/example_app/app/models/page.rb @@ -0,0 +1,3 @@ +class Page < ApplicationRecord + belongs_to :product +end diff --git a/spec/example_app/app/models/product.rb b/spec/example_app/app/models/product.rb index 35dc9e673cda4f0d1acc8bd506b438d5cedeac8e..3df36e60378c004d761b07805173cd93e8e04acd 100644 --- a/spec/example_app/app/models/product.rb +++ b/spec/example_app/app/models/product.rb @@ -8,6 +8,7 @@ class Product < ApplicationRecord end has_many :line_items, dependent: :destroy + has_many :pages, dependent: :destroy has_one :product_meta_tag, dependent: :destroy validates :description, presence: true diff --git a/spec/example_app/app/policies/page_policy.rb b/spec/example_app/app/policies/page_policy.rb new file mode 100644 index 0000000000000000000000000000000000000000..7d681ef3d27a96604455bfee3b0c428ab0642bfe --- /dev/null +++ b/spec/example_app/app/policies/page_policy.rb @@ -0,0 +1,2 @@ +class PagePolicy < ApplicationPolicy +end diff --git a/spec/example_app/config/routes.rb b/spec/example_app/config/routes.rb index 98123b7953c6bcdae53429a00842a800fcaa98c7..7c08884f650527632da91fdf765051357ad8fda0 100644 --- a/spec/example_app/config/routes.rb +++ b/spec/example_app/config/routes.rb @@ -4,6 +4,7 @@ Rails.application.routes.draw do resources :line_items resources :log_entries resources :orders + resources :pages resources :products resources :product_meta_tags, except: [:index] resources :payments, only: [:index, :show] diff --git a/spec/example_app/db/migrate/20200714081950_create_pages.rb b/spec/example_app/db/migrate/20200714081950_create_pages.rb new file mode 100644 index 0000000000000000000000000000000000000000..7eb89915117b93feec8452ef3c45b5561b601065 --- /dev/null +++ b/spec/example_app/db/migrate/20200714081950_create_pages.rb @@ -0,0 +1,11 @@ +class CreatePages < ActiveRecord::Migration[6.0] + def change + create_table :pages do |t| + t.string :title + t.text :body + t.belongs_to :product, foreign_key: true + + t.timestamps + end + end +end diff --git a/spec/example_app/db/schema.rb b/spec/example_app/db/schema.rb index 0608b17e424ed73e6925121b83f4ca3422452400..308929609feaceb428493efa7ccb9ff132113f6f 100644 --- a/spec/example_app/db/schema.rb +++ b/spec/example_app/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_03_26_202615) do +ActiveRecord::Schema.define(version: 2020_07_14_081950) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -77,6 +77,15 @@ ActiveRecord::Schema.define(version: 2020_03_26_202615) do t.index ["customer_id"], name: "index_orders_on_customer_id" end + create_table "pages", force: :cascade do |t| + t.string "title" + t.text "body" + t.bigint "product_id" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + t.index ["product_id"], name: "index_pages_on_product_id" + end + create_table "payments", id: :serial, force: :cascade do |t| t.integer "order_id" t.datetime "created_at", null: false @@ -111,5 +120,6 @@ ActiveRecord::Schema.define(version: 2020_03_26_202615) do add_foreign_key "line_items", "orders" add_foreign_key "line_items", "products" add_foreign_key "orders", "customers" + add_foreign_key "pages", "products" add_foreign_key "payments", "orders" end diff --git a/spec/example_app/db/seeds.rb b/spec/example_app/db/seeds.rb index e7ca242210eea28e1e036cf1429466b9edb64f2b..af2b7f5893ffa1af35aa023ea3e72c4d9aeb51cf 100644 --- a/spec/example_app/db/seeds.rb +++ b/spec/example_app/db/seeds.rb @@ -54,6 +54,24 @@ product_attributes.each do |attributes| Product.create! attributes.merge(price: 20 + rand(50)) end +Product.find_each do |p| + Page.create!( + title: "Something about #{p.name}", + body: Faker::Lorem.paragraph, + product: p, + ) + Page.create!( + title: "The secrets of the game #{p.name}", + body: Faker::Lorem.paragraph, + product: p, + ) + Page.create!( + title: "If you liked #{p.name}, you will love these games", + body: Faker::Lorem.paragraph, + product: p, + ) +end + customers.each do |customer| (1..3).to_a.sample.times do order = Order.create!( diff --git a/spec/example_app/spec/features/pagination_spec.rb b/spec/example_app/spec/features/pagination_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..e922649d914e62af56952df0c61b900d0dfb4eab --- /dev/null +++ b/spec/example_app/spec/features/pagination_spec.rb @@ -0,0 +1,88 @@ +require "rails_helper" + +search_input_selector = ".search__input" + +RSpec.feature "Pagination", type: :feature do + def expect_to_appear_in_order(*elements) + positions = elements.map { |e| page.body.index(e) } + expect(positions).to eq(positions.sort) + end + + it "paginates records based on a query param" do + customers = create_list(:customer, 2) + + visit admin_customers_path(per_page: 1) + + expect(page).not_to have_content(customers.last.name) + click_on "Next" + expect(page).to have_content(customers.last.name) + end + + describe "sorting" do + it "allows sorting by columns" do + create(:customer, name: "unique name two") + create(:customer, name: "unique name one") + + visit admin_customers_path + click_on "Name" + + expect_to_appear_in_order("unique name one", "unique name two") + end + + it "allows clicking through after sorting", :js do + customer = create(:customer) + create(:order, customer: customer) + + visit admin_customers_path + click_on "Name" + find("[data-url]").click + expect(page).to have_header("Show #{customer.name}") + end + + it "allows reverse sorting" do + create(:customer, name: "unique name one") + create(:customer, name: "unique name two") + + visit admin_customers_path + 2.times { click_on "Name" } + + expect_to_appear_in_order("unique name two", "unique name one") + end + + it "toggles the order" do + create(:customer, name: "unique name one") + create(:customer, name: "unique name two") + + visit admin_customers_path + 3.times { click_on "Name" } + + expect_to_appear_in_order("unique name one", "unique name two") + end + + it "preserves search" do + query = "bar@baz.com" + + visit admin_customers_path(search: query) + click_on "Name" + + expect(find(search_input_selector).value).to eq(query) + end + end + + context "with resources of type Page" do + it "can paginate and sort" do + FactoryBot.create(:page, title: "Page 2") + FactoryBot.create(:page, title: "Page 4") + FactoryBot.create(:page, title: "Page 1") + FactoryBot.create(:page, title: "Page 5") + FactoryBot.create(:page, title: "Page 3") + + visit admin_pages_path(per_page: 3) + click_on "Title" + expect_to_appear_in_order("Page 1", "Page 2", "Page 3") + + click_on "Next" + expect_to_appear_in_order("Page 4", "Page 5") + end + end +end diff --git a/spec/factories.rb b/spec/factories.rb index fd87fb2abaaa9f2ca01cb7ae6b616a10b04ba42c..82752358df29ae3efc269dd039689039fe7a0be4 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -69,4 +69,6 @@ FactoryBot.define do sequence(:name) { |n| "Country #{n}" } sequence(:code) { |n| "C#{n}" } end + + factory :page end diff --git a/spec/features/index_page_spec.rb b/spec/features/index_page_spec.rb index faa8880cfc789cbef42fe58f3ba1df4eb2c1dccc..7bc86fc1ecfbad773c38c16bcccd83f1949d7ae7 100644 --- a/spec/features/index_page_spec.rb +++ b/spec/features/index_page_spec.rb @@ -68,72 +68,6 @@ describe "customer index page" do expect(page).to have_table_header(custom_label) end end - - it "paginates records based on a constant" do - customers = create_list(:customer, 2) - - visit admin_customers_path(per_page: 1) - - expect(page).not_to have_content(customers.last.name) - click_on "Next" - expect(page).to have_content(customers.last.name) - end - - describe "sorting" do - def expect_to_appear_in_order(*elements) - positions = elements.map { |e| page.body.index(e) } - expect(positions).to eq(positions.sort) - end - - it "allows sorting by columns" do - create(:customer, name: "unique name two") - create(:customer, name: "unique name one") - - visit admin_customers_path - click_on "Name" - - expect_to_appear_in_order("unique name one", "unique name two") - end - - it "allows clicking through after sorting", :js do - customer = create(:customer) - create(:order, customer: customer) - - visit admin_customers_path - click_on "Name" - find("[data-url]").click - expect(page).to have_header("Show #{customer.name}") - end - - it "allows reverse sorting" do - create(:customer, name: "unique name one") - create(:customer, name: "unique name two") - - visit admin_customers_path - 2.times { click_on "Name" } - - expect_to_appear_in_order("unique name two", "unique name one") - end - - it "toggles the order" do - create(:customer, name: "unique name one") - create(:customer, name: "unique name two") - - visit admin_customers_path - 3.times { click_on "Name" } - - expect_to_appear_in_order("unique name one", "unique name two") - end - - it "preserves search" do - query = "bar@baz.com" - - visit admin_customers_path(search: query) - click_on "Name" - - expect(find(search_input_selector).value).to eq(query) - end - end end describe "search input" do