I am still trying to find a good solution to the Delegated Type feature and as I didn't find any good more detailed guide, I would like to ask here.
What I am interested in is what DDH said:
Delegated types. With this approach, the “superclass” is a concrete class that is represented by its own table, where all the superclass attributes that are shared amongst all the “subclasses” are stored. And then each of the subclasses have their own individual tables for additional attributes that are particular to their implementation.
In their example, I saw that they use the creator on superclass and is a shared attribute for the subclasses, and they are using that in the comments controller like:
Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user
In this case, the creator
will be always the same, so correctly is implemented like that.
My question :
(As they mention) what if you want the superclass to keep the title attribute (just an example), which all the other subclasses can use, how can I handle that? In this case, the title is mutable (value will be different on each subclass based on user input), how it should be implemented on the subclass controller.
random example:
Note: ofc I created the Productable module and included in the subclass models
# schema.rb
ActiveRecord::Schema.define(version: 2021_08_23_191445) do
create_table "laptops", force: :cascade do |t|
t.integer "usb_ports"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "mobiles", force: :cascade do |t|
t.integer "front_camera"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
create_table "Product", force: :cascade do |t|
t.string "title"
t.string "description"
t.string "productable_type"
t.integer "productable_id"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
end
# laptops_controller.rb
class LaptopsController < ApplicationController
def new
@laptop = Laptop.new
end
def create
@laptop = Product.create! productable: Laptop.new(laptop_params) # Here to add what for the title?
redirect_to @laptop
end
private
def set_laptop
@laptop = Laptop.find(params[:id])
end
def laptop_params
params.require(:laptop).permit(:usb_ports)
end
end
# _form.html.erb
<%= form_with(model: @laptop) do |form| %>
<div class="field">
<%= form.label :usb_ports %>
<%= form.number_field :usb_ports %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
Should I use nested attributes as with polymorphic associations? Does anyone have any suggestions? Or maybe, to add the title attribute on each subclass and the attributes, and on superclass to add only the attributes that never change? But then, what's the point?
Thank you :)
and on superclass to add only the attributes that never change
I think you are misreading the docs. I didn't know about this feature until today (so thank you for drawing my attention to it), but from what I can see, the goal of using a superclass like this is not to save space by reusing/sharing fields that are the same for all records (if they are truly the same for all records, they don't need to be fields. Just hardcode them or put into a config file).
So if you're creating Comments or Messages, each new comment or message will create its own Entry (the delegated superclass in this example). An Entry won't be shared and is therefore free to have mutable fields.
And yes, since this feature seems to be just a layer of sugar over polymorphic associations, you can/should use all the same methods (nested attributes, etc.)
In case someone else faces the same issue, the accepts_nested_attributes_for
option wasn't available for delegated_type
when I was looking for that, hence I couldn't use nested forms for associated objects configured via delegated_type
.
BUT: Rails 7 adds accepts_nested_attributes_for
support to delegated_type
https://github.com/rails/rails/pull/41717 🎉
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.