I have model Category (categories of Images)
class Category < ApplicationRecord
has_many :images, foreign_key: 'category_id', dependent: :destroy
has_many :subscriptions, foreign_key: "category_id", dependent: :destroy
has_many :subscribed_users, :through => :subscriptions, :source => :user
end
Model Category has many subscribtions and subscribed users
class Subscription < ApplicationRecord
belongs_to :user
belongs_to :category
validates :user_id, presence: true
validates :category_id, presence: true
end
class User < ApplicationRecord
has_many :images, foreign_key: 'user_id', dependent: :destroy
has_many :categories, foreign_key: 'user_id', dependent: :destroy
has_many :likes, foreign_key: "user_id", dependent: :destroy
has_many :liked_images, :through => :likes, :source => :images
has_many :comments, foreign_key: "user_id", dependent: :destroy
has_many :commented_images, :through => :comments, :source => :images
has_many :subscriptions, foreign_key: 'user_id', dependent: :destroy
has_many :subscribed_categories, :through => :subscriptions, :source => :categories
end
Also I have model Image
class Image < ApplicationRecord
belongs_to :user
belongs_to :category
has_many :likes, foreign_key: "image_id", dependent: :destroy
has_many :liking_users, :through => :likes, :source => :user
has_many :comments, foreign_key: "image_id", dependent: :destroy
has_many :commenting_users, :through => :comments, :source => :user
end
which has many likes and comments (comments and likes to Image, not to categories of image)
class Like < ApplicationRecord
belongs_to :user
belongs_to :image
validates :user_id, presence: true
validates :image_id, presence: true
end
class Comment < ApplicationRecord
belongs_to :user
belongs_to :image
validates :user_id, presence: true
validates :image_id, presence: true
end
I need to select from database 5 most popular categories.
The most popular category is category which has highest count of likes, comments and images at the same time.
I made one query, which select all images, that has the highest count of likes and comments:
#top_images = Image.left_outer_joins(:likes).distinct.select('images.*, COUNT(likes.*) AS likes_count').left_outer_joins(:comments).distinct.select('images.*, COUNT(comments.*) AS comments_count').group(
'images.id').order("likes_count DESC").order("comments_count DESC")
Also I make query which select categories, which has more images:
#top_categories_img_count = Category.left_outer_joins(:images).distinct.select('categories.*, COUNT(images.*) AS images_count').group(
'categories.id').order("images_count DESC")
But I have no idea how to select all categories which have highest count of images, likes and comments
Related
I have User and Organization model. User has_many :organizations and Organization has_many :users.
When I want to destroy user from db using #user.destroy I get error Key (id)=(3) is still referenced from table "organizations".
Here is my User and Organization models:
Organization.rb
class Organization < ApplicationRecord
extend FriendlyId
friendly_id :name, :use => :slugged
has_many :members, :dependent => :destroy
has_many :users, :through => :members, :dependent => :destroy
has_many :moderators, -> { where :members => { :role => 1 } }, :through => :members, :source => :user
has_many :admins, -> { where :members => { :role => 2 } }, :through => :members, :source => :user
has_many :campains, :dependent => :destroy
has_many :statuses, :as => :statusable
has_many :activities
has_many :world_members
has_many :teams
accepts_nested_attributes_for :members, :users
User.rb
class User < ApplicationRecord
extend FriendlyId
friendly_id :full_name, :use => :slugged
acts_as_voter
enum role: [:user, :moderator, :organization, :admin]
has_many :members, :class_name => "Member", :foreign_key => "user_id", :dependent => :destroy
has_many :organizations, :through => :members, :dependent => :destroy
has_many :conversations, :foreign_key => :sender_id
has_many :admin_organizations, ->{ where(members: {role: 2}) }, :through => :members, source: :organization
has_many :moderate_organizations, ->{ where(members: {role: 1}) }, :through => :members, source: :organization
has_many :member_organizations, ->{ where(members: {role: 0}) }, :through => :members, source: :organization
accepts_nested_attributes_for :members, :organizations
Member.rb
class Member < ApplicationRecord
enum role: [:member, :moderator, :admin]
belongs_to :user
belongs_to :organization
You should not have dependent_destroy for :organizations or :users, just for :members.
You do not have direct relation from organization to user, nor from user to organization.
class User < ActiveRecord::Base
has_many :members, dependent: :destroy
has_many :organizations, through: :members
end
class Organization < ActiveRecord::Base
has_many :members, dependent: :destroy
has_many :users, through: :members
end
class Member < ActiveRecord::Base
belongs_to :user
belongs_to :organization
end
As you do not want to delete all users for example from an organization, just there reference to the organization and vice verse if you delete user, you do not want to delete all organizations on which user was connected to, just the reference
I have 3 models set up as follows:
class User < ActiveRecord::Base
has_many :interests, as: :interesting, dependent: :destroy
has_many :games, through: :interests, source: :interesting, source_type: 'Game'
has_many :people, through: :interests, source: :interesting, source_type: 'Person'
end
class Interest < ActiveRecord::Base
belongs_to :interesting, polymorphic: true
validates :user_id, presence: true
validates :interesting_id, presence: true
end
class Game < ActiveRecord::Base
has_many :users, through: :interests
has_many :interests, as: :interesting
end
class Person < ActiveRecord::Base
has_many :users, through: :interests
has_many :interests, as: :interesting
end
When I try to call user.games the SQL run on the database is
SELECT "games".* FROM "games"
INNER JOIN "interests"
ON "game"."id" = "interests"."interesting_id"
WHERE "interests"."interesting_id" = $1 AND
"interests"."interesting_type" = $2 AND
"interests"."interesting_type" = $3
[["interesting_id", 3],
["interesting_type", "User"],
["interesting_type", "Game"]]
so obviously nothing is returned. The query should work, as long as ["interesting_type", "User"] isn't included.
What am I doing wrong? What is the best way to set up the User class as well as the Game and Person class?
I'm using Rails v4.2.6
So to summarize, the following appears to work in this use case:
User < ActiveRecord::Base
has_many :interests, dependent: :destroy
has_many :games, through: :interests,
source: :interesting, source_type: 'Game'
has_many :people, through: :interests,
source: :interesting, source_type: 'Person'
end
class Interest < ActiveRecord::Base
belongs_to :user
belongs_to :interesting, polymorphic: true
validates :user_id, presence: true
validates :interesting_id, presence: true
end
Please trying this
class User < ActiveRecord::Base
has_many :interests, dependent: :destroy
has_many :games, as: :interesting, through: :interests, source_type: 'Game'
has_many :people, as: :interesting, through: :interests, source_type: 'Person'
end
class Interest < ActiveRecord::Base
belongs_to :interesting, polymorphic: true
validates :user_id, presence: true # I don't know the reason to use that if you use as polymorphic
validates :interesting_id, presence: true
end
The table_name interests it should have only the attributes :id:, :interesting_id, :interesting_type
In my app I have 3 models: Item, Category and Categorization defined as below:
class Item < ActiveRecord::Base
attr_accessible :name, :description
has_many :categorizations
has_many :categories, :through => :categorizations
end
class Category < ActiveRecord::Base
attr_accessible :name, :description, :parent, :children, :items, :parent_id
has_many :children, :class_name => "Category", :foreign_key => "parent_id", :dependent => :nullify
belongs_to :parent, :class_name => "Category"
has_many :categorizations
has_many :items, :through => :categorizations
end
class Categorization < ActiveRecord::Base
attr_accessible :category, :item
belongs_to :category
belongs_to :item
end
However, doing this:
Category.where(:parent_id => self.id).includes(:items)
won't return me the items associated to the category. What am I missing here?
Try this:
Category.where(parent_id: id).joins(:items)
Try this:
Category.where(:parent_id => id).collect(&:items)
It will return the items of all categories matching the where clause.
I am trying to add a counter cache on a a column in a self join association.
I have two models User and followings. User has followers and followees, who are from the user table itself.
User.rb
has_many :followings
has_many :followers, :through => :followings
has_many :followees, :through => :followings
Following.rb
class Following < ActiveRecord::Base
attr_accessible :followee_id, :follower_id
belongs_to :follower, :class_name => "User"
belongs_to :followee, :class_name => "User"
end
now i want to add counter cache on follower and followees. I have followers_count and followees_count columns in user table.
I tried
belongs_to :follower, :class_name => "User" , :counter_cache => true
But this doesn't return any data in the user table.
Any help would be appreciated.
It was long-long time ago, but
User.rb
class User < ActiveRecord::Base
has_many :followings_as_follower, class_name: 'Following', foreign_key: 'follower_id', dependent: :destroy
has_many :followings_as_followee, class_name: 'Following', foreign_key: 'followee_id', dependent: :destroy
has_many :followers, through: :followings_as_followee, source: :follower
has_many :followees, through: :followings_as_follower, source: :followee
def follow?(user)
followees.reload.include? user
end
def follow(user)
return if follow?(user)
followings_as_follower.create(followee: user)
end
def unfollow(user)
return unless follow?(user)
followings_as_follower.where(followee: user).first.destroy
end
end
Following.rb
class Following < ActiveRecord::Base
belongs_to :follower, class_name: 'User', counter_cache: :followees_count
belongs_to :followee, class_name: 'User', counter_cache: :followers_count
validates :follower, presence: true
validates :followee, presence: true
validates :followee, uniqueness: { scope: [:follower, :followee] }
end
Try this,
belongs_to :follower, foreign_key: 'the_id_of_foreign_key', class_name: 'User', counter_cache: :followers_count
You can use the column_name instead of true in counter_cache.
I have simplified my design to make this question more clear. (Design of models below)
What I am trying to do is from a CourseEnrollment get all the PatientCourseSteps for that enrollment only (An enrollment consists of a patient and a course).
Here is what I have tried:
#Gives me ALL the patient course steps regardless of the course
course_enrollment.patient.patient_course_steps
#Gives me ALL the patient course steps regardless of the patient
course_enrollment.course.patient_course_steps
Below is the models that are necessary
class CourseEnrollment < ActiveRecord::Base
belongs_to :patient
belongs_to :course
end
class Course < ActiveRecord::Base
has_many :course_steps, :dependent => :destroy
has_many :steps, :through => :course_steps
has_many :course_enrollments, :dependent => :destroy
has_many :patients, :through =>:course_enrollments
has_many :patient_course_steps, :dependent => :destroy
end
class Patient < ActiveRecord::Base
belongs_to :user, :dependent => :destroy
has_many :enrollments, :dependent => :destroy
has_many :clients, :through => :enrollments
has_many :course_enrollments, :dependent => :destroy
has_many :courses, :through => :course_enrollments
has_many :patient_course_steps, :dependent => :destroy
end
class Step < ActiveRecord::Base
belongs_to :step_type
belongs_to :client
has_one :step_quiz, :dependent => :destroy
has_one :step_survey, :dependent => :destroy
has_one :step_text, :dependent => :destroy
has_one :step_download, :dependent => :destroy
has_one :step_video, :dependent => :destroy
has_one :step_presentation, :dependent => :destroy
has_many :course_steps, :dependent => :destroy
has_many :courses, :through => :course_steps
has_many :patient_course_steps, :dependent => :destroy
end
class PatientCourseStep < ActiveRecord::Base
belongs_to :patient
belongs_to :course
belongs_to :step
end
What I ended up doing was adding a method to CourseEnrollment named patient_course_steps which queries for what I need.
def patient_course_steps
PatientCourseStep.where(:patient_id => self.patient_id, :course_id => self.course_id)
end