Comments (4)
@Jay0921 While this should work as well, overriding primary_key
is less preferable just because I find it semantically incorrect. I treat primary_key
as a term coming from the db-level and I would prefer it to reflect the actual state of the database schema. This is why query_constraints
is a little better option since it will behave as a "virtual primary key" while not making primary_key
value misleading.
But ultimately I agree that there is a legit issue (limitation) in current Rails capabilities and it needs to be addressed
from rails.
Hey, I created a reproduction script (with a potential fix included) so we can be sure we are discussing the same model setup:
# frozen_string_literal: true
require "bundler/inline"
gemfile(true) do
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem "rails"
# If you want to test against edge Rails replace the previous line with this:
# gem "rails", github: "rails/rails", branch: "main"
gem "sqlite3"
end
require "active_record"
require "minitest/autorun"
require "logger"
# This connection will do for database-independent bug reports.
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Schema.define do
create_table :tickers, id: false, force: true do |t|
t.integer :gvkey
t.primary_key :iid
end
create_table :co_actions, id: false, force: true do |t|
t.integer :gvkey
t.primary_key :iid
end
end
class Ticker < ActiveRecord::Base
query_constraints :gvkey, :iid
end
class CoAction < ActiveRecord::Base
belongs_to :ticker, query_constraints: [:gvkey, :iid]
end
class BugTest < Minitest::Test
def test_association_stuff
ticker = Ticker.create!(gvkey: 123)
CoAction.create!(gvkey: 123, iid: ticker.iid)
assert_equal ticker, CoAction.take.ticker
end
end
While I think your situation may be considered as a limitation in Rails I just wanted to share that there is a high chance that by defining query_constraints :gvkey, :iid
on the Ticker
model you'll get the behavior you are looking for.
It will lead to the Ticker
objects to be always referenced by two columns and models that belongs_to :ticker
may need to explicitly set primary_key: :iid
if they want to reference it by just one column but overall this should be a working solution to at least get you unblocked
from rails.
Hey @nvasilevski. Thanks for the quick response. I think the problem is conceptual. With the singular primary/foreign keys I was able to specify both (primary and foreign) in the relation and override the primary_key defined in the class but now, with the composite primary key, I'm only able to specify the foreign_key in the relation but the primary key is always taken from the class.
Going back to the schema. The ticker model has its own singular primary key and it connects to other models (except co_action) using its own key. Here is the schema:
ActiveRecord::Schema.define do
create_table :tickers, id: true, force: true do |t|
t.integer :gvkey
t.integer :iid
end
create_table :co_actions, id: true, force: true do |t|
t.integer :gvkey
t.integer :iid
end
end
class Ticker < ActiveRecord::Base
has_many :co_actions, primary_key: [:gvkey, :iid], foreign_key: [:gvkey, :iid]
end
class CoAction < ActiveRecord::Base
belongs_to :ticker, query_constraints: [:gvkey, :iid], primary_key: [:gvkey, :iid]
end
class BugTest < Minitest::Test
def test_association_stuff
ticker = Ticker.create!(gvkey: 123, iid: 321)
CoAction.create!(gvkey: 123, iid: 321)
assert_equal ticker, CoAction.take.ticker
end
end
I understand that the schema looks weird but the co_actions
table is given by a 3rd party provider so I can't add a ticker_id
column to it.
BTW I was able to patch it. I just override the relation's @association_primary_key
right after adding the relation:
class CoAction < ActiveRecord::Base
belongs_to :ticker, query_constraints: [:gvkey, :iid], primary_key: [:gvkey, :iid]
reflections['ticker'].instance_variable_set(:@association_primary_key, ['gvkey', 'iid'])
end
from rails.
@bguban I'm not sure if this will resolve the problem.
class Ticker < ActiveRecord::Base
self.primary_key = [:gvkey, :iid]
has_many :co_actions, query_constraints: [:gvkey, :iid]
end
class CoAction < ActiveRecord::Base
self.primary_key = [:gvkey, :iid]
belongs_to :ticker, query_constraints: [:gvkey, :iid]
end
from rails.
Related Issues (20)
- Make it possible for ConnectionPool#disconnect to avoid reconnection HOT 1
- Syntax error on first db:migrate after upgrading to rails 6 HOT 4
- Multiple rate-limits share same cache key so it increments multiple time for single request
- UniquenessValidator raises error when used on singleton class HOT 13
- Errors reported when ActionMailer emails are sent via ActiveJob do not filter mailer params, potentially leak sensitive data HOT 9
- Mapping column manually like type/class to c_type/c_class HOT 4
- "Cannot expire connection, it is owned by a different thread" in Rails 7.2 tests HOT 4
- Rails console reload! command HOT 3
- Precision and scale not detected for custom DOMAIN types [PostgreSQL]
- Fresh Rails project contains rubocop linter violation
- ActionCable stream_from handlers not called in test
- Bug in generated Dockerfile when using ruby preview versions HOT 2
- Remove deprecated code
- HashWithIndifferentAccess#deep_stringify_keys vs non-string keys HOT 4
- # Contributor Code of Conduct The Rails team is committed to fostering a welcoming community. **Our Code of Conduct can be found here**: https://rubyonrails.org/conduct For a history of updates, see the page history here: https://github.com/rails/website/commits/main/_pages/conduct.html
- ActiveRecord model instance's singleton class raises exception when 'inspect' is called on it
- ActiveSupport::HashWithIndifferentAccess and the splat operator HOT 3
- `ActiveRecord::Persistence#reload` doesn't preload nested associations with strict loading enabled
- .true? and false? HOT 3
- activerecord/test/cases/encryption/extended_deterministic_queries_test.rb
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rails.