ruby-on-rails 如何显示来自一个控制器的多个型号的列表?

vlju58qv  于 2023-02-20  发布在  Ruby
关注(0)|答案(3)|浏览(169)

假设我正在构建一个动物园应用程序,并且为每种动物类型实现了一个模型:哺乳动物,鸟类,爬行动物,无脊椎动物,鱼类和两栖动物。所有这些都有一个标题,描述,和图像字段,但他们可能有一些其他字段以及。我将如何能够显示所有动物从一个控制器的字母顺序列表?我想让他们使用自己的部分。

py49o6xq

py49o6xq1#

我怎样才能从一个控制器中按字母顺序显示所有动物的列表?
如果他们都在不同的table上,选择就不好了。
1.把它们全部载入内存并分类。如果动物不是那么多的话,这个方法可能有效。
1.创建一个SQL view,它执行一个SQL union,使它们看起来像一个表,然后在那个视图上执行一个order by
另一种方法是将所有动物放入一个表中,然后使用“单表继承”将类型区分为子类。

$ bin/rails generate model animal type:string title:string description:string

class Animal < ApplicationRecord
  def eat
    ...
  end

  def drink
    ...
  end

  def make_little_animals
    ...
  end
end

class Mammal < Animal
  def lactate
  end
end

class Bird < Animal
  def make_little_animals
    lay_egg
  end

  def lay_egg
    ...
  end

  def fly?
    ...
  end
end

所有这三个都将存储在animals中。Animal.order(:title)将返回所有按标题排序的动物。但类型为Bird的动物将作为Bird对象加载。类型为Mammal的动物将作为Mammal对象加载。Bird.all将只返回类型为Bird的动物。
考虑一下你是否需要子类,如果它们没有任何不同的功能,那么就为它们的分类法添加一列,并确定一些范围。

class Animal < ApplicationRecord
  scope :mammals -> { where(taxonomic_class: :mammalia }
  scope :birds -> { where(taxonomic_class: :aves }

  def eat
    ...
  end

  def drink
    ...
  end

  def make_little_animals
    ...
  end
end

然后你可以要求所有的动物Animal.order(:title)或只是鸟类Animal.birds.order(:title)
我建议从那里开始。你可以在以后把它分成子类。

plupiseo

plupiseo2#

我发现了两个很好的选项,但仍然不确定我是否会遇到显示为列表的问题:
1 -创建多表继承,如here所示。

class Animal < ActiveRecord::Base
  def eat
  end
end

class Bird < Animal
  set_table_name "birds"
  
  def fly
  end
end

class Mammal < Animal
  set_table_name "mammals"
  
  def run
  end
end

class Fish < Animal
  set_table_name "fish"
  
  def swim
  end
end

class CreateMammal < ActiveRecord::Migration
  def change
    create_table :mammals do |t|
      t.integer :num_of_legs
      
      # ... more column fields #
      t.timestamps
    end
  end
end

class CreateFish < ActiveRecord::Migration
  def change
    create_table :fish do |t|
      t.integer :num_of_fins
      
      # ... more column fields #
      t.timestamps
    end
  end
end

class CreateBird < ActiveRecord::Migration
  def change
    create_table :birds do |t|
      t.float   :wing_span
      
      # ... more column fields #
      t.timestamps
    end
  end
end
view raw

2 -创建类似于here所示产品示例的内容。

class ActiveRecord::Base
  def self.acts_as_product
    include Sellable
  end
end

class ProductProperties < ActiveRecord::Base
  belongs_to :sellable, :polymorphic => true, :dependent => :destroy
  validates_presence_of :title # for example
end

module Sellable
  def self.included(base)
    base.has_one :product_properties, :as => :sellable, :autosave => true
    base.validate :product_properties_must_be_valid
    base.alias_method_chain :product_properties, :autobuild
    base.extend ClassMethods
    base.define_product_properties_accessors
  end

  def product_properties_with_autobuild
    product_properties_without_autobuild || build_product_properties
  end

  def method_missing(meth, *args, &blk)
    product_properties.send(meth, *args, &blk)
  rescue NoMethodError
    super
  end

  module ClassMethods
    def define_product_properties_accessors
      all_attributes = ProductProperties.content_columns.map(&:name)
      ignored_attributes = ["created_at", "updated_at", "sellable_type"]
      attributes_to_delegate = all_attributes - ignored_attributes
      attributes_to_delegate.each do |attrib|
        class_eval <<-RUBY
          def #{attrib}
            product_properties.#{attrib}
          end

          def #{attrib}=(value)
            self.product_properties.#{attrib} = value
          end

          def #{attrib}?
            self.product_properties.#{attrib}?
          end
        RUBY
      end
    end
  end

  protected

  def product_properties_must_be_valid
    unless product_properties.valid?
      product_properties.errors.each do |attr, message|
        errors.add(attr, message)
      end
    end
  end
end

class Tee < ActiveRecord::Base
  acts_as_product
end

class Pen < ActiveRecord::Base
  acts_as_product
end
6psbrbz9

6psbrbz93#

我建议使用委托类型,如here所述:

# Schema: entries[ id, account_id, creator_id, created_at, updated_at, entryable_type, entryable_id ]
class Entry < ApplicationRecord
  belongs_to :account
  belongs_to :creator
  delegated_type :entryable, types: %w[ Message Comment ]
end

module Entryable
  extend ActiveSupport::Concern

  included do
    has_one :entry, as: :entryable, touch: true
  end
end

# Schema: messages[ id, subject ]
class Message < ApplicationRecord
  include Entryable
  has_rich_text :content
end

# Schema: comments[ id, content ]
class Comment < ApplicationRecord
  include Entryable
end

相关问题