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
Define a Method That Is a Closure in Ruby
Switching Between Web and Touch Interfaces on Facebook Login Using Omniauth and Rails 3
Testing Whether String Starts with or End with Another String
How to Delete All Contents of a Folder with Ruby-Rails
Possible to Alias a Belongs_To Association in Rails
How to Call Applicationcontroller Methods from Applicationhelper
How to Get Request.Uri in Model in Rails
Creating Categories on Jekyll Driven Site
How to Read the Body Text of an Email Using Ruby's Net/Imap Library
Ruby Classes: Initialize Self VS. @Variable
How to Use Nokogiri to Parse an Xml File
Starting or Restarting Unicorn with Capistrano 3.X
Why Should I Use Rspec or Shoulda with Rails
Can't Use Compass After Installing It
Reading the First Line of a File in Ruby
Best Practice About Empty Belongs_To Association
How to Write Specs for Code That Depends on Environment Variables