Override Activerecord << Operator on Has_Many :Through Relationship, to Accept Data for the Join Model

Override ActiveRecord operator on has_many :through relationship, to accept data for the join model

You can use the proxy_association helper inside the block to get the association and proxy_association.owner to get the Directory object itself. See here for some more info on this.

how to access rails join model attributes when using has_many :through

In your example you have defined in Item model relationship as has_many for collection_items and collections the generated association method is collection_items and collections respectively both of them returns an array so the way you are trying to access here is wrong. this is primarily case of mant to many relationship. just check this Asscociation Documentation for further reference.

Rails: Overriding ActiveRecord association method

You can use block with has_many to extend your association with methods. See comment "Use a block to extend your associations" here.

Overriding existing methods also works, don't know whether it is a good idea however.

  has_many :tags, :through => :taggings, :order => :name do
def << (value)
"overriden" #your code here
super value
end
end

has_and_belongs_to_many, avoiding dupes in the join table

I worked around this by creating a before_save filter that fixes stuff up.

class Post < ActiveRecord::Base 
has_and_belongs_to_many :tags
before_save :fix_tags

def tag_list= (tag_list)
self.tags.clear
tag_list.strip.split(' ').each do
self.tags.build(:name => tag)
end
end

def fix_tags
if self.tags.loaded?
new_tags = []
self.tags.each do |tag|
if existing = Tag.find_by_name(tag.name)
new_tags << existing
else
new_tags << tag
end
end

self.tags = new_tags
end
end

end

It could be slightly optimised to work in batches with the tags, also it may need some slightly better transactional support.

Rails ActiveRecord Shovel () Operator

When you use the shovel operator (<<), Rails automatically saves the associated object. So, when you do this:

self.comments << @new_comment

@new_comment is added to the comments collection and instantly fires update SQL without waiting for the save or update call on the parent object, unless the parent object is a new record.

From this documentation

collection<<(object, …) Adds one or more objects to the collection by
creating associations in the join table (collection.push and
collection.concat are aliases to this method). Note that this
operation instantly fires update SQL without waiting for the save or
update call on the parent object, unless the parent object is a new
record.

Rails has_many through a HABTM relationship

I would say this isn't a really good solution.

In ActiveRecord you can't actually define associations where the foreign key can potentially be in two different columns like this:

has_many :games, ->(team) { where('home_team_id = ? or away_team_id = ?', team.id, team.id) }, class_name: 'Game'

It definitely won't work as Rails will still join the assocation as JOIN games ON games.team_id = teams.id. Just adding a WHERE clause to the query won't fix that. Since ActiveRecord actually creates a variety of different queries there is no option to simply provide a different join.

A kludge to make this work would be to add an instance method:

class Game < ApplicationRecord
def users
User.joins(:teams)
.where(teams: { id: home_team.id })
.or(Team.where(id: away_team.id))
end
end

As its not an actual association you cant join through it or use an sort of eager loading to avoid n+1 queries.

If you actually want to create a single association that you can join through you would need to add a join table between games and teams.

class Team < ApplicationRecord
# ...
has_many :game_teams
has_many :games, through: :game_teams
end

# rails g model game_team team:belongs_to game:belongs_to score:integer
class GameTeam < ApplicationRecord
belongs_to :team
belongs_to :game
end

class Game < ApplicationRecord
has_many :game_teams
has_many :teams, through: :game_teams
has_many :users, through: :teams
end

This is a better idea since it gives you a logical place to record the score per team.

As an aside if the composition of teams can change and accurate record keeping is important you might actually need additional join tables as the lineup when a game is played may not actually match the current lineup.



Related Topics



Leave a reply



Submit