Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nested has one field #207

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
36 changes: 36 additions & 0 deletions app/views/madmin/fields/nested_has_one/_form.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<div class="block md:inline-block md:w-32 flex-shrink-0 text-gray-700">
<%= render "madmin/shared/label", form: form, field: field %>
</div>
<%= content_tag :div, class: "border border-gray-200 rounded-lg p-5" do %>
<%= form.fields_for(
field.attribute_name,
form.object.public_send(field.attribute_name) || field.to_model.new,
{}
) do |nested_form| %>
<% field.nested_attributes.each do |name, nested_attribute| %>
<% next if nested_attribute[:field].nil? %>
<% next unless nested_attribute[:field].visible?(action_name) %>
<% next unless nested_attribute[:field].visible?(:form) %>

<% nested_field = nested_attribute[:field] %>

<div class="mb-4 flex">
<%= render(
partial: nested_field.to_partial_path("form"),
locals: {
field: nested_field,
record: nested_form.object,
form: nested_form,
resource: field.resource
}
)%>
</div>
<% end %>
<div class="mb-4 flex">
<div class="block md:inline-block md:w-32 flex-shrink-0 text-red-500">
<%= nested_form.label :_destroy %>
</div>
<%= nested_form.check_box :_destroy, class: "form-checkbox text-red-600 checked:ring-red-600 focus:ring-red-600" %>
</div>
<% end %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/madmin/fields/nested_has_one/_index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% if (object = field.value(record)) %>
<%= link_to Madmin.resource_for(object).display_name(object), Madmin.resource_for(object).show_path(object) %>
<% end %>
3 changes: 3 additions & 0 deletions app/views/madmin/fields/nested_has_one/_show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<% if (object = field.value(record)) %>
<%= link_to Madmin.resource_for(object).display_name(object), Madmin.resource_for(object).show_path(object) %>
<% end %>
1 change: 1 addition & 0 deletions lib/madmin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module Fields
autoload :Integer, "madmin/fields/integer"
autoload :Json, "madmin/fields/json"
autoload :NestedHasMany, "madmin/fields/nested_has_many"
autoload :NestedHasOne, "madmin/fields/nested_has_one"
autoload :Password, "madmin/fields/password"
autoload :Polymorphic, "madmin/fields/polymorphic"
autoload :RichText, "madmin/fields/rich_text"
Expand Down
32 changes: 32 additions & 0 deletions lib/madmin/fields/nested_has_one.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module Madmin
module Fields
class NestedHasOne < Field
DEFAULT_ATTRIBUTES = %w[_destroy id].freeze
def nested_attributes
resource.attributes.except(*skipped_fields)
end

def resource
"#{to_model.name}Resource".constantize
end

def to_param
{"#{attribute_name}_attributes": permitted_fields}
end

def to_model
attribute_name.to_s.singularize.classify.constantize
end

private

def permitted_fields
(resource.permitted_params - skipped_fields + DEFAULT_ATTRIBUTES).uniq
end

def skipped_fields
options[:skip] || []
end
end
end
end
3 changes: 2 additions & 1 deletion lib/madmin/resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ def field_for_type(type)
has_many: Fields::HasMany,
has_one: Fields::HasOne,
rich_text: Fields::RichText,
nested_has_many: Fields::NestedHasMany
nested_has_many: Fields::NestedHasMany,
nested_has_one: Fields::NestedHasOne
}.fetch(type)
end

Expand Down
4 changes: 4 additions & 0 deletions test/dummy/app/controllers/madmin/post_stats_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Madmin
class PostStatsController < Madmin::ResourceController
end
end
1 change: 1 addition & 0 deletions test/dummy/app/madmin/resources/post_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class PostResource < Madmin::Resource
attribute :versions, form: false
attribute :user
attribute :comments
attribute :post_stat, :nested_has_one, skip: %I[shared]

# Scopes
scope :recent
Expand Down
26 changes: 26 additions & 0 deletions test/dummy/app/madmin/resources/post_stat_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
class PostStatResource < Madmin::Resource
# Attributes
attribute :id, form: false
attribute :drafts_saved
attribute :keywords
attribute :shared
attribute :created_at, form: false
attribute :updated_at, form: false

# Associations
attribute :post

# Uncomment this to customize the display name of records in the admin area.
# def self.display_name(record)
# record.name
# end

# Uncomment this to customize the default sort column and direction.
# def self.default_sort_column
# "created_at"
# end
#
# def self.default_sort_direction
# "desc"
# end
end
2 changes: 2 additions & 0 deletions test/dummy/app/models/post.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ class Post < ApplicationRecord
has_paper_trail

belongs_to :user
has_one :post_stat
accepts_nested_attributes_for :post_stat, allow_destroy: true
has_many :comments, as: :commentable, dependent: :destroy
has_many_attached :attachments
has_one_attached :image
Expand Down
3 changes: 3 additions & 0 deletions test/dummy/app/models/post_stat.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class PostStat < ApplicationRecord
belongs_to :post
end
1 change: 1 addition & 0 deletions test/dummy/config/routes/madmin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
patch :archive
end
end
resources :post_stats
namespace :action_text do
resources :rich_texts
end
Expand Down
12 changes: 12 additions & 0 deletions test/dummy/db/migrate/20240515044320_create_post_stats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
class CreatePostStats < ActiveRecord::Migration[7.1]
def change
create_table :post_stats do |t|
t.references :post, foreign_key: true
t.integer :drafts_saved
t.string :keywords
t.boolean :shared, default: false

t.timestamps
end
end
end
42 changes: 26 additions & 16 deletions test/dummy/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 2021_09_21_230902) do

ActiveRecord::Schema[7.1].define(version: 2024_05_15_044320) do
create_table "action_mailbox_inbound_emails", force: :cascade do |t|
t.bigint "status", default: 0, null: false
t.string "message_id", null: false
t.string "message_checksum", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["message_id", "message_checksum"], name: "index_action_mailbox_inbound_emails_uniqueness", unique: true
end

Expand All @@ -26,8 +25,8 @@
t.text "body"
t.string "record_type", null: false
t.bigint "record_id", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true
end

Expand Down Expand Up @@ -64,8 +63,8 @@
t.string "commentable_type", null: false
t.bigint "commentable_id", null: false
t.text "body"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["commentable_type", "commentable_id"], name: "index_comments_on_commentable_type_and_commentable_id"
t.index ["user_id"], name: "index_comments_on_user_id"
end
Expand All @@ -77,8 +76,18 @@
create_table "numericals", force: :cascade do |t|
t.decimal "decimal"
t.float "float"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "post_stats", force: :cascade do |t|
t.integer "post_id"
t.integer "drafts_saved"
t.string "keywords"
t.boolean "shared", default: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["post_id"], name: "index_post_stats_on_post_id"
end

create_table "posts", force: :cascade do |t|
Expand All @@ -87,16 +96,16 @@
t.integer "comments_count"
t.integer "state"
t.json "metadata"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_posts_on_user_id"
end

create_table "user_connected_accounts", force: :cascade do |t|
t.bigint "user_id", null: false
t.string "service"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_user_connected_accounts_on_user_id"
end

Expand All @@ -114,8 +123,8 @@
t.string "password_digest"
t.string "token"
t.string "ssn"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.json "settings"
t.text "preferences"
end
Expand All @@ -134,5 +143,6 @@
add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id"
add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id"
add_foreign_key "comments", "users"
add_foreign_key "post_stats", "posts"
add_foreign_key "user_connected_accounts", "users"
end
7 changes: 7 additions & 0 deletions test/dummy/test/models/post_stat_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require "test_helper"

class PostStatTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end