Rails saving nested model association, has_many through - ruby-on-rails

class Task < ActiveRecord::Base
belongs_to :project, :inverse_of => :tasks
accepts_nested_attributes_for :project
end
class Project < ActiveRecord::Base
belongs_to :workspace, :inverse_of => :projects
has_many :tasks, :inverse_of => :project,
dependent: :destroy,
autosave: true
accepts_nested_attributes_for :workspace
end
class Workspace < ActiveRecord::Base
has_many :projects, inverse_of: :workspace,
dependent: :destroy,
autosave: true
has_many :tasks, through: :projects
end
I am able to save the child object 'project' from 'workspace'. But I can't save the grandchild object 'task' from 'workspace'. What's wrong? How can I do that without additional '.save' calls? I don't want to call #p.save
####child####
#w = Workspace.first
#p = #w.projects.new(name: "text")
#w.save
#p.new_record? #false, which is ok
###grandchild###
#w = Workspace.first
#p = #w.projects.first
#t = #p.tasks.new(name: "text")
#w.save
#t.new_record? #true, but should've been saved

Related

ActiveRecord grab shared model from polymorphic association

I'm looking for a better way to query Users from 2 different Models used in a polymorphic association. Here is the setup
class Schedule < ApplicationRecord
belongs_to :announcement
has_many :targets, dependent: :destroy
has_many :lists, through: :targets, source: :target, source_type: 'List'
has_many :accounts, through: :targets, source: :target, source_type: 'Account'
end
class Target < ApplicationRecord
# belongs_to :announcement
belongs_to :schedule
belongs_to :target, polymorphic: true
delegate :announcement, to: :schedule
end
class List < ApplicationRecord
belongs_to :account
has_many :targets, as: :target, dependent: :destroy
has_many :lists_users
has_many :users, through: :lists_users
end
class Account < ApplicationRecord
has_many :announcements, dependent: :destroy
has_many :targets, as: :target, dependent: :destroy
has_many :users, dependent: :destroy
end
At the moment I'm solving this by creating a method inside the Schedule model that grabs Users this way:
def subscribers
targets.map(&:target).map(&:users).flatten.uniq
end
I looked at something similar with this question, but didn't seem to solve it.
I would do that like this:
class Schedule < ApplicationRecord
def subscribers
# fetch all associated user IDs
lists_user_ids = lists.joins(:lists_users).distinct.pluck("lists_users.user_id")
accounts_user_ids = accounts.joins(:users).distinct.pluck("users.id")
user_ids = (lists_user_ids + accounts_user_ids).uniq
# fetch users by IDs
User.where(id: user_ids)
end
end

How do target polymorphic model through many models

I have 4 classes:
class User < ApplicationRecord
has_many :memories
has_many :playlists
has_many :items, as: 'playlist_items', through: :playlists
has_many :items, as: 'memory_items', through: :memories
end
class Item < ApplicationRecord
belongs_to :itemable, polymorphic: true, optional: true
end
class Playlist < ApplicationRecord
belongs_to :user
has_many :items, as: :itemable, dependent: :destroy
accepts_nested_attributes_for :items, allow_destroy: true
end
class Memory < ApplicationRecord
belongs_to :user
has_many :items, as: :itemable, dependent: :destroy
accepts_nested_attributes_for :items, allow_destroy: true
end
I would like to be able to get from current_user to the items of either type, i.e. Memory or Playlist. But right now I can only get to 1 set.. if I have this in User:
has_many :items, through: :playlists
I can't currently figure out how to do both in a list. 'As' seems to have no effect. Any suggestions would be very helpful?
You can't have both associations with the same name, you can specialize specifying the source. Try like this:
class User < ApplicationRecord
has_many :memories
has_many :playlists
has_many :playlist_items, through: :playlists, source: :items
has_many :memory_items, through: :memories, source: :items
end
Then of course you use user.playlist_items and user.memory_items instead.

How get data of model association rails

How can i get data of model association
this are my models.
user.rb
has_many :movie
has_many :quality
has_many :option
movie.rb
belongs_to :user
has_many :quality, :dependent => :destroy
quality.rb
belongs_to :movie
belongs_to :user
has_many :option
option.rb
belongs_to :user
belongs_to :quality
has_one :movie, :through => :quality
this is my controller
movie_controller.rb
def show
#movie = Movie.find(params[:id])
end
In my view i have this.
-#movie.qualities.option do |o|
=o.name
diagram
I want to get all the names of the qualities of a movie.
Please help me.
You need to change all has many relationship to plural
has_many :movies
has_many :qualities
has_many :options
# etc
and option belongs_to movie
Your final code should look like this
user.rb
has_many :movies
has_many :qualities, through: :movies
has_many :options, through: :qualities
movie.rb
belongs_to :user
has_many :qualities, dependent: :destroy
quality.rb
belongs_to :movie
has_one :user, through: :movie
has_many :options
option.rb
belongs_to :quality
has_one :user, through: :quality
has_one :movie, through: :quality
movie_controller.rb
def show
#movie = Movie.find(params[:id])
end
View should be like this.
- #movie.qualities.each do |quality|
- quality.options.each do |option|
= option.name
Cheers :)

has_one :through polymorphic - is it possible?

I have models in my app:
class Comment < ActiveRecord::Base
belongs_to :commentable, :polymorphic => true
end
class Project < ActiveRecord::Base
has_many :discussions, :dependent => :destroy
has_many :tickets, :dependent => :destroy
end
class Discussion < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
class Ticket < ActiveRecord::Base
has_many :comments, :as => :commentable, :dependent => :destroy
end
Everything works fine, but sometimes it's not very convinient to get project from comment through commentable, i.e. comment.commentable.project.
Is there any way to make has_one project in Comment model?
I would add the following method to your class Comment:
def project
self.commentable ? self.commentable.project : nil
end
This will give you the same result without all the magic of ActivRecord.

:has_many relationship with :through on another relationship with :through

My setup is as follows:
class User < ActiveRecord::Base
has_many :owners, :dependent => :destroy
has_many :properties, :through => :owners
end
class Owner < ActiveRecord::Base
belongs_to :user
belongs_to :property
end
class Property < ActiveRecord::Base
has_many :owners, :dependent => :destroy
has_many :users, :through => :owners
has_many :datafiles, :dependent => :destroy
end
class Datafile < ActiveRecord::Base
belongs_to :property
end
Now I'd like to be able to do #user.datafiles.
I tried has_many :datafiles, :through => :properties, :source => :datafiles but there appears to be a problem with a :through on something that's already went to a :through. So how would I go about to try and manage what I'm trying to do here?
Thank you in advance.
2 approaches;
1>
class User < AR
has_many :owners, :dependent => :destroy
has_many :properties, :through => :owners
has_many datafiles
end
class Datafile < AR
belongs_to :user
belongs_to :property
end
Your requirement of user.datafiles should be fulfilled with this.
If you want a nested has_many through, you'll need to use a plugin which is the 2nd approach.
2>
You can find it here.
The plugin works out of the box and does the job.
How about something like:
#user.rb
def datafiles
Property.find(:all, :joins => :owners, :conditions => ['owners.user_id = self.id'], :include => :datafile).collect(&:datafile)

Resources