简体   繁体   中英

Delegated types - Ruby on Rails

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM