简体   繁体   中英

How to set up a nested model with Ruby on Rails?

I'm newbie in coding, and I'm discovering RoR. I want to create an application with Users and Products. I'm good with the Users, but I'm wondering about the architecture of the Products...

Here the Product model I imagine :

Product :

- Name
- Owner
- Borrower
- Location
    - Address
    - GPS Coordinates
- Comments
    - Title
    - Content
    - User
- Category

And here are my main models :

Class User
    has_many :owned_products, class_name: "Product", foreign_key: "owner_id"
    has_many :borrowed_products, class_name: "Product", foreign_key: "borrower_id"
    has_one :location, as: :localizable
end

$ rails generate model Location address:string coordinates:string
Class Location
    belongs_to :localizable, polymorphic: true
end

$ rails generate model Comment title:string content:text user_id:integer
Class Comments
    belongs_to :product
    has_one :user
end

$ rails generate model Product name:string owner_id:integer borrower_id:integer location_id:integer comment_id:integer category_id:integer
Class Product
    belongs_to :owner, class_name: "User", foreign_key: "owner_id"
    belongs_to :borrower, class_name: "User", foreign_key: "borrower_id"
    has_one :location, as: :localizable
    has_many :comments
    has_one :category
end

So, I'm wondering if I must create every category sub-model like this :

- Consumption
    - Name
    - Utility
    - Builder
- Culture
    - Title
    - Barcode
    - Type
        - Book
            - Author
            - Publisher
        - Video
            - Length
            - Format
- Food
    - Name
    - Cooking Date
    - Weight

Which I would write down like :

$ rails generate model Category consumption_id:integer culture_id:integer food_id:integer
Class Category
    belongs_to :product
    has_one :consumption
    has_one :culture
    has_one :food
end

  $ rails generate model Consumption name:string utility:string builder:string
  Class Consumption
      belongs_to :category
  end


  $ rails generate model Culture title:string barcode:integer type_id:integer
  Class Culture
      belongs_to :category
      has_one :type
  end

    $ rails generate model Type book_id:integer video_id:integer
    Class Type
        belongs_to :culture
        has_one :book
        has_one :video
    end

      $ rails generate model Book author:string publisher:string
      Class Book
          belongs_to :type
      end

      $ rails generate model Video length:string format:string
      Class Video
          belongs_to :type
      end

  $ rails generate model Food name:string cooking_date:datetime weight:float
  Class Food
      belongs_to :category
  end

Or if it would be better to keep it at only one level like this :

- Category_type (consumption, culture, or food)
- Name (or title)
- Utility
- Builder
- Barcode
- Culture_type
- Author
- Publisher
- Length
- Format
- Cooking_date
- Weight

which would give me :

$ rails generate model Category category_type:string name:string utility:string builder:string barcode:integer culture_type:string author:string publisher:string length:integer format:string cooking_date:datetime weight:float
Class Category
    belongs_to :product
end

I feel like the first way is more understandable, but I doubt it would be as efficient as the second. Can you give me a hint ?


Accordingly to @r4m, here is what I did :

$ rails generate model Category
Class Category
    belongs_to :product
    belongs_to :categorizable, polymorphic: true
end

  $ rails generate model Consumption name:string utility:string builder:string
  Class Consumption
      has_many :categories, :as => :categorizable
  end


  $ rails generate model Culture title:string barcode:integer type_id:integer
  Class Culture
      has_many :categories, :as => :categorizable
      has_one :type
  end

  $ rails generate model Food name:string cooking_date:datetime weight:float
  Class Food
      has_many :categories, :as => :categorizable
  end

And I changed the Category's migration to :

class CreateCategories < ActiveRecord::Migration
  def change
    create_table :categories do |t|
      t.references :categorizable, polymorphic: true
      t.timestamps
    end
  end
end

But it doesn't seem very understandable to me...

If I want to grab every "consumption" products of @user, how could I do ? Do something like that would be able to work ?

@consumptions = @user.products.consumptions

Suppose you have an array of foods that belong to the same category (and the same consumption and culture parameters). With the last model you have a lot of redundancy since you cannot assign an array to a row, in this case a row of the Category table (see here for Rails supported types). You would be forced to replicate the same information, regarding the category details, just to assign those foods entries as single entities instead of an array.

You need to consider the first solution you propose, because associations allow you to create relations between different models (for example arrays to arrays in the case of the "many to many" relationship).

In addition I suggest to you to use polymorphic association to simplify Category model, see here .

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