-
Notifications
You must be signed in to change notification settings - Fork 33
Add support for :through
associations
#630
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
class Country < ApplicationRecord | ||
has_one :flag, dependent: :destroy | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# frozen_string_literal: true | ||
|
||
class Flag < ApplicationRecord | ||
belongs_to :country | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,8 @@ class User < ApplicationRecord | |
validates :first_name, presence: true | ||
has_one :profile | ||
scope :adult, -> { where(age: 18..) } | ||
has_one :location, class_name: "Country" | ||
belongs_to :location, class_name: "Country" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Going off of the schema I'm pretty sure this was incorrectly set up, as I don't see any tests that expect this to be invalid. |
||
has_one :country_flag, through: :location, source: :flag | ||
|
||
attr_readonly :last_name | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class CreateFlags < ActiveRecord::Migration[8.0] | ||
def change | ||
create_table :flags do |t| | ||
t.references :country, null: false, foreign_key: true | ||
|
||
t.timestamps | ||
end | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,32 @@ class Organization < ActiveRecord::Base | |
assert_equal(2, response[0].range.end.line) | ||
end | ||
|
||
test "recognizes has_many :through model associations" do | ||
response = generate_definitions_for_source(<<~RUBY, { line: 4, character: 29 }) | ||
# typed: false | ||
|
||
class Organization < ActiveRecord::Base | ||
has_many :memberships | ||
has_many :users, through: :memberships | ||
end | ||
RUBY | ||
|
||
assert_equal(2, response.size) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
assert_equal( | ||
URI::Generic.from_path(path: File.join(dummy_root, "app", "models", "user.rb")).to_s, | ||
response[0].uri, | ||
) | ||
assert_equal( | ||
URI::Generic.from_path(path: File.join(dummy_root, "app", "models", "membership.rb")).to_s, | ||
response[1].uri, | ||
) | ||
assert_equal(2, response[0].range.start.line) | ||
assert_equal(2, response[0].range.end.line) | ||
assert_equal(2, response[1].range.start.line) | ||
assert_equal(2, response[1].range.end.line) | ||
end | ||
|
||
test "recognizes belongs_to model associations" do | ||
response = generate_definitions_for_source(<<~RUBY, { line: 3, character: 14 }) | ||
# typed: false | ||
|
@@ -90,6 +116,32 @@ class User < ActiveRecord::Base | |
assert_equal(2, response[0].range.end.line) | ||
end | ||
|
||
test "recognizes has_one :through model associations" do | ||
response = generate_definitions_for_source(<<~RUBY, { line: 4, character: 35 }) | ||
# typed: false | ||
|
||
class User < ActiveRecord::Base | ||
belongs_to :location, class_name: "Country" | ||
has_one :country_flag, through: :location, source: :flag | ||
end | ||
RUBY | ||
|
||
assert_equal(2, response.size) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
assert_equal( | ||
URI::Generic.from_path(path: File.join(dummy_root, "app", "models", "flag.rb")).to_s, | ||
response[0].uri, | ||
) | ||
assert_equal( | ||
URI::Generic.from_path(path: File.join(dummy_root, "app", "models", "country.rb")).to_s, | ||
response[1].uri, | ||
) | ||
assert_equal(2, response[0].range.start.line) | ||
assert_equal(2, response[0].range.end.line) | ||
assert_equal(2, response[1].range.start.line) | ||
assert_equal(2, response[1].range.end.line) | ||
end | ||
|
||
test "recognizes has_and_belongs_to_many model associations" do | ||
response = generate_definitions_for_source(<<~RUBY, { line: 3, character: 27 }) | ||
# typed: false | ||
|
@@ -110,11 +162,11 @@ class Profile < ActiveRecord::Base | |
end | ||
|
||
test "handles class_name argument for associations" do | ||
response = generate_definitions_for_source(<<~RUBY, { line: 3, character: 11 }) | ||
response = generate_definitions_for_source(<<~RUBY, { line: 3, character: 14 }) | ||
# typed: false | ||
|
||
class User < ActiveRecord::Base | ||
has_one :location, class_name: "Country" | ||
belongs_to :location, class_name: "Country" | ||
end | ||
RUBY | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to understand the intended experience, when going to definition you'd see both the association and the
through
association as options, correct?Also, the
node.arguments
return is nilable for when there are no arguments. I think we can restructure this a bit.handle_association
method, we can get the arguments and return early if it's nil.through