My instance method of active_posts is not working on my User model.
I am grabbing a user record, then for that record I need to join the blogs and posts table, and then filter by the post's active attribute in order to return only the active posts for that user.
class User < ApplicationRecord
has_many :blogs
has_many :posts, through: :blogs
def active_posts
joins(blogs: :posts).merge(Post.active).distinct
end
end
class Blog < ApplicationRecord
belongs_to :user
has_many :posts
end
class Post < ApplicationRecord
belongs_to :blog
belongs_to :user, through: :blog
scope :active, -> {where(active: true}
end
I run the following:
User.first.active_posts
And here is the error:
NoMethodError
Undefined method 'joins' on the user record
Just realized my error.
Just call posts.active within the active_posts method.
def active_posts
posts.active
end
joins is used for a collection. So you would use joins on a class method in your model, not within an instance method. Simple error.
Related
In my Post model, I have
has_many :followers
In my Follower model, I have
belongs_to :model
belongs_to :owner,polymorphic: true
In my User and Admin devise models, I have
has_many :followers,as: :owner
Requirement: I want to have something like Post.owners and it should return me a list of all users and/or admins that are following this post.
I'm not sure, but I think that AR doesn't provide a way to load polymorphic associations in just one query. But you can use:
post = Post.find(1)
post_followers = post.followers.includes(:owner)
post_owners = post_followers.map(&:owner)
The solution you're looking for is polymorphic has many through. You can add these lines in your model of User and Admin.
has_many :followers
has_many :posts, through: :followers, source: :owner, source_type: 'Owner'
I think you want something like this:
class Post < ApplicationRecord
belongs_to :owner, polymorphic: true
end
class User < ApplicationRecord
has_many :posts, as: :owner
end
class Follower < ApplicationRecord
has_many :posts, as: :owner
end
From an instance of your User you can then retrieve their posts with #user.posts
The same goes for your Follower, #follower.posts
If you want to get to the parent of your post instance, you can do so via #post.owner. To make this work, however, we need to set up the schema correctly by declaring both a foreign key column and a type column in the model that declares the polymorphic interface using the references form:
class CreatePosts < ActiveRecord::Migration[5.0]
def change
create_table :posts do |t|
# your attribs here
t.references :owner, polymorphic: true, index: true
end
end
end
Three models: Post, Comment, Rating.
Post
class Post < ApplicationRecord
has_many :comments
has_many :ratings, through: :comments
end
Comment
class Comment < ApplicationRecord
belongs_to :post
has_one :rating
end
Rating
class Rating < ApplicationRecord
belongs_to :comment
end
I want to be able to do call a method on Post model (to for example calculate mean_rating) when the Rating record gets added or removed to my database.
I am able to to this with calling the post model method inside rating model after_create and after_destroy but I am wondering if there is a way to update Post model using dependent or any other methods?
Any ideas?
You could create a method in your Post model:
class Post < ApplicationRecord
has_many :comments
has_many :ratings, through: :comments
def average_rating
ratings.average(:note)
end
end
And call it on your instances:
post = Post.last
post.average_rating
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
class User < ActiveRecord::Base
has_many :posts
end
class Category < ActiveRecord::Base
has_many :posts
end
I want to get all the posts that have a relation to user AND category. Is any similar possible:
user.category.posts
Or do I need to do:
user.posts.where(category_id: category.id)
You have 1-M relationship between User and Post.
In User model association should be has_many :posts (note plural)and not has_many :post(singular).
Update your model User as below:
class User < ActiveRecord::Base
has_many :posts ## Plural posts
end
To answer below question:
get all the posts that have a relation to user AND category
Assuming that you have local variables user and category as an instance of User model and Category model respectively.
For example:
user = User.find(1); ## Get user with id 1
category = Category.find(1); ## Get category with id 1
user.posts.where(category_id: category.id) ## would get you what you need.
Also, user.category.posts will not work as User and Category models are not associated.
Try:-
user.posts.where(category_id: category.id)
Change your association like
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :category
end
class User < ActiveRecord::Base
has_many :post
belongs_to :category or has_one :category
end
class Category < ActiveRecord::Base
has_one :user or belongs_to :user
has_many :posts
end
in users table add column category_id,or add column user_id in categories,because you don't have relation between those two tables.if you don't have relation you can't use association API's.then you have to use manual API to fetch the data.like how you have mentioned your question.
What is the best way to implement something like a board in pinterest (a collection of objects) in rails. I am trying to come with it, it seems more like an array implementation.
Here's my logic for the associations : User have many collections, user have many pins , collections belongs to user.
User class
class User < ActiveRecord::Base
has_many :pins, through: :collections
has_many :collections
end
Pins class
class Pin < ActiveRecord::Base
belongs_to :user
has_many :collections
end
Collections class
class Collection < ActiveRecord::base
belongs_to :user
end
So now here's my confusion, how to implement a controller that will allow me to create a collection and inside this collection object, create or push pins and save them as another object for the current_user. Hope I'm making sense
Here's the controller
class CollectionsController < ApplicationController
def create
#collection = current_user.collections.new(params[:collection])
#this where i'm confused , if it an array , how to implement it , to push or create a pin object inside ?
end
end
You have to use nested attributes for this.
Check this http://currentricity.wordpress.com/2011/09/04/the-definitive-guide-to-accepts_nested_attributes_for-a-model-in-rails-3/.
Basically what you need is:
# collection model
accepts_nested_attributes_for :pins
# view, see also nested_form in github
f.fields_for :pins
You're looking for the has_many_through association. See section 2.4 on the Rails guide: http://guides.rubyonrails.org/association_basics.html
class User < ActiveRecord::Base
has_many :collections
end
class Pin < ActiveRecord::Base
has_many :collections, through: :pinnings
end
class Pinning < ActiveRecord::Base
belongs_to :pin
belongs_to :collection
end
class Collection < ActiveRecord::base
belongs_to :user
has_many :pins, through: :pinnings
end
How to create a new record in after_save using other model?
I tried this line which resulted "undefined method `journals' for nil:NilClass"
e.g.
resources :users do
resource :profile
resources :journals
end
class User < ActiveRecord::Base
has_one :profile
has_many :journals
end
class Profile < ActiveRecord::Base
belongs_to :user
after_save :create_new_journal_if_none
private
def create_new_journal_if_none
if user.journals.empty? ????
user.journals.build() ????
end
end
end
class Journals < ActiveRecord::Base
belong_to :user
end
Nested models are going to be saved as well once parent saves, so it's easy to use before_create block and build a nested resource here.
class Profile < ActiveRecord::Base
belongs_to :user
before_create do
user.journals.build unless user.journals.any?
end
end
This line of code will create a profile and a journal assigned with the User
User.find(1).create_profile(name :test)