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)
- accepts_nested_attributes_for doesn't validate unchanged objects HOT 2
- Rails server --pid option does not seem to work as expected. Also no documentation found. HOT 2
- `ActiveRecord::NotNullViolation` for Missing Enum Default in Rails 7 HOT 7
- No connection pool for 'ActiveRecord::Base' found for the 'reading' role. #275 HOT 4
- trix with rails 7.0 giving TypeError HOT 2
- in guides.rubyonrails documentation of threads: missing info about db access HOT 1
- HasMany/HasOne associations: combining `:through` and a scope including a `.merge` leads to missing table HOT 1
- [Question] Why doesn't set_pk_sequence! support the parameter for is_called? HOT 5
- Rails 6.0.6.1 transaction rollback doesn't reload object HOT 1
- Error `undefined method `start_with?' for nil` when logging
- new_framework_defaults initializer for Rails 7.1 not setting ActiveRecord.run_after_transaction_callbacks_in_order_defined
- [Feature Request][CSP] Support for multiple Content Security Policies HOT 2
- ActionCable: Invalid channel causes repeated subscription attempts
- Code generation memory bloat post alias fix HOT 8
- Rails throws an error when sending invalid UTF-8 query param HOT 1
- Lazy default_scope evaluation in joined models loses original context
- Some Rails integration tests break with rack 3.1 HOT 4
- ActionText Editor Previews uploaded pre 7.1.3.4 are broken in 7.1.3.4 after a resave HOT 13
- Inversion of associations with :through don't work until it's saved
- Incorrect `has_many through` load with custom association name and custom keys type
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.