I am making a basic app for the growing incel online community linking them to various pieces of literature they could find useful, helpful and guiding. I am having difficulty creating proper associations.
I have several models:
- User: user.rb, a model of a user to view, comment and like books.
- like: like.rb, like model to assign likes to books.
- comment: comment.rb, comment model to comment on book models (via a user).
- book: book.rb, model for books, will route/view pdf's to host server.
- bookshares: book_share.rb, will be a join table linking users to likes to comments to books and so on and vice versa.
- godmodel: hypothetical model not yet implemented to link together everything in an all encompassing manner.
So, I want users to be able to be create with a username and be able to view, like and comment books on the 'website' that will eventually be migrated over to a android app. Here is my abysmal code:
class BookShare < ApplicationRecord
validates :book_id, presence: true, uniqueness: true
validates :viewer_id, presence: true, uniqueness: true
belongs_to :user
belongs_to :book
belongs_to :comment
end
class Book < ApplicationRecord
validates :title, presence: true
validates :author, presence: true
validates :user_id, presence: true
validates :isbn, presence: true
validates :title, presence: true
has_many :book_shares
has_many :users, through: :book_shares
has_many :likes, through: :book_shares
has_many :comments, through: :book_shares
end
class Comment < ApplicationRecord
validates :user_id, presence: true, uniqueness: true
validates :book_id, presence: true, uniqueness: true
validates :title, presence: true
has_many :book_shares
has_many :books, through: :book_shares
end
class GodModel < ApplicationRecord
has_many :books
has_many :users
has_many :comments
#has_many :likes
has_many :topics
has_many :book_shares
end
class Like < ApplicationRecord
# not fully implemented yet.
validates :user_id, presence: true
belongs_to :user
end
class User < ApplicationRecord
validates :username, presence: true, uniqueness: true
has_many :book_shares
has_many :comments, through: :book_shares
has_many :books, through: :book_shares
end
class Topic < ApplicationRecord
# not implemented yet
end
Here is my schema:
ActiveRecord::Schema[7.0].define(version: 2022_04_12_145402) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "book_shares", force: :cascade do |t|
t.integer "book_id", null: false
t.integer "viewer_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["book_id", "viewer_id"], name: "index_book_shares_on_book_id_and_viewer_id", unique: true
t.index ["book_id"], name: "index_book_shares_on_book_id"
t.index ["viewer_id"], name: "index_book_shares_on_viewer_id"
end
create_table "books", force: :cascade do |t|
t.string "title", null: false
t.string "author", null: false
t.integer "user_id", null: false
t.text "body_info"
t.integer "isbn", null: false
t.binary "photo"
t.binary "r_data"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_books_on_user_id"
end
create_table "comments", force: :cascade do |t|
t.integer "user_id", null: false
t.integer "book_id", null: false
t.text "body_txt"
t.string "title"
t.binary "photo"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["book_id"], name: "index_comments_on_book_id"
t.index ["user_id"], name: "index_comments_on_user_id"
end
create_table "god_models", force: :cascade do |t|
t.string "title"
t.integer "user_id"
t.integer "comment_id"
t.integer "book_share_id"
t.integer "book_id"
t.integer "like"
t.integer "topic"
t.binary "data_x"
t.date "today"
t.binary "title2"
t.boolean "nullfy"
t.float "nums"
t.text "body"
t.datetime "create_at_"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["body"], name: "index_god_models_on_body"
t.index ["book_id"], name: "index_god_models_on_book_id"
t.index ["book_share_id"], name: "index_god_models_on_book_share_id"
t.index ["comment_id"], name: "index_god_models_on_comment_id"
t.index ["data_x"], name: "index_god_models_on_data_x"
t.index ["like"], name: "index_god_models_on_like"
t.index ["nullfy"], name: "index_god_models_on_nullfy"
t.index ["nums"], name: "index_god_models_on_nums"
t.index ["title2"], name: "index_god_models_on_title2"
t.index ["today"], name: "index_god_models_on_today"
t.index ["topic"], name: "index_god_models_on_topic"
t.index ["user_id"], name: "index_god_models_on_user_id"
end
create_table "likes", force: :cascade do |t|
t.integer "user_id"
t.string "likeable_type"
t.bigint "likeable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["likeable_type", "likeable_id"], name: "index_likes_on_likeable"
t.index ["user_id", "likeable_type", "likeable_id"], name: "index_likes_on_user_id_and_likeable_type_and_likeable_id", unique: true
end
create_table "users", force: :cascade do |t|
t.string "username", null: false
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["username"], name: "index_users_on_username", unique: true
end
end
Example controller:
class UsersController < ApplicationController
def index
render plain: 'index'
end
def show
render plain: 'show'
end
def new
render plain: 'new'
end
def destroy
render plain: 'destroy'
end
def update
redner update: 'update'
end
private
def usershare_param
params.require(:user).permit(:username)
end
end
This is what I produced so far. I am able to create the model object, save them I think and populate their fields but I don't think my models are working with the given associations.
I tried using erd but it does not work. Given the use of my app is the models/associations correctly made? I want to have a user who can view/comment/like books of interest. A book can have many likes and comments, books can be viewed by many users, users can like and comment many books, topics will be implemented later to assort the books. The entire mechanism of liking/commenting/viewing via a user(s) will be implemented via a joins table called bookshares. I want to write my associations correctly before moving onto the view/routes part of the mini-protect.
CodePudding user response:
With 4 tables, books
, users
, comments
and likes
. You can implement the given design.
a book can have many likers(users), a user can like many books, forms many-to-many relationship between users and books. Make likes
a join table.
Similarly, a book has many comments, a user can write many comments. Make comments
a join table between users and books with extra fields specific to comment.
# app/models/book.rb
has_many :likes, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :lovers, through: :likes, source: :user
has_many :commentors, through: :comments, source: :user
# app/models/user.rb
has_many :likes, dependent: :destroy
has_many :comments, dependent: :destroy
has_many :fav_books, through: :likes, source: :book
# app/models/like.rb
belongs_to :book
belongs_to :user
# app/models/comment.rb
belongs_to :book
belongs_to :user
You can consult this guide to explore topics in more depth.