Skip to content

Commit b0997b0

Browse files
authored
Merge pull request #23 from bdurand/extract-type-from-yaml
Documentation no longer calls data methods to get types
2 parents 733bd72 + 2b06bbf commit b0997b0

6 files changed

Lines changed: 38 additions & 26 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## 1.6.1
8+
9+
### Fixed
10+
11+
- Fixed issue with YARD and RBS documentation tasks possibly raising an error if a named value method is deprecated and wrapped to return an error. Types are now inferred directly from the data rather than calling a method.
12+
713
## 1.6.0
814

915
### Added

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.6.0
1+
1.6.1

lib/support_table_data/documentation/rbs_doc.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def instance_signatures(name)
4242
lines << "def self.#{name}: () -> #{klass.name}"
4343
lines << "def #{name}?: () -> bool"
4444
klass.support_table_attribute_helpers.each do |attribute_name|
45-
return_type = TypeInference.rbs_type(TypeInference.value_type(klass, "#{name}_#{attribute_name}"))
45+
return_type = TypeInference.rbs_type(TypeInference.value_type(klass, name, attribute_name))
4646
lines << "def self.#{name}_#{attribute_name}: () -> #{return_type}"
4747
end
4848
lines

lib/support_table_data/documentation/type_inference.rb

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,28 @@
33
module SupportTableData
44
module Documentation
55
# Infers documentation types for the dynamically-defined attribute helpers
6-
# by calling the generated method and inspecting the class of the value
7-
# it returns. The values returned by these helpers are frozen literals from
8-
# the parsed data file, so this does not require a database connection.
9-
#
10-
# This module must not be used on finder helpers (e.g. `Color.red`), which
11-
# call `find_by!` and would hit the database.
6+
# by reading the canonical value out of the parsed data file and
7+
# inspecting its class. This avoids invoking the generated method, which
8+
# may have been wrapped (e.g. deprecated) to raise.
129
module TypeInference
1310
module_function
1411

15-
# Determine the documentation type for an attribute helper by calling
16-
# the method and looking at the class of the returned value. Returns
17-
# nil when the method is not defined.
12+
# Determine the documentation type for a named-instance attribute
13+
# helper by looking up the attribute value in the model's named
14+
# instance data and returning its class. Returns nil when the
15+
# attribute is not defined for the named instance.
1816
#
1917
# @param klass [Class] The model class
20-
# @param method_name [String, Symbol] The class method name to call
18+
# @param name [String, Symbol] The named instance name
19+
# @param attribute_name [String, Symbol] The attribute name
2120
# @return [Class, nil]
22-
def value_type(klass, method_name)
23-
return nil unless klass.respond_to?(method_name)
21+
def value_type(klass, name, attribute_name)
22+
return nil unless klass.respond_to?(:named_instance_data)
2423

25-
klass.public_send(method_name).class
24+
data = klass.named_instance_data(name)
25+
return nil unless data.is_a?(Hash) && data.key?(attribute_name.to_s)
26+
27+
data[attribute_name.to_s].class
2628
end
2729

2830
# Map a Ruby value class to a YARD type string.

lib/support_table_data/documentation/yard_doc.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ def compact_instance_block(name)
175175
end
176176

177177
def attribute_yard_return_type(name, attribute_name)
178-
TypeInference.yard_type(TypeInference.value_type(klass, "#{name}_#{attribute_name}"))
178+
TypeInference.yard_type(TypeInference.value_type(klass, name, attribute_name))
179179
end
180180
end
181181
end

spec/support_table_data/documentation/type_inference_spec.rb

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,26 @@
44

55
RSpec.describe SupportTableData::Documentation::TypeInference do
66
describe ".value_type" do
7-
it "returns the class of the value returned by the helper method" do
7+
it "returns the class of the value from the named instance data" do
88
# Group has named_instance_attribute_helpers :group_id, :name
9-
expect(described_class.value_type(Group, "primary_name")).to eq(String)
10-
expect(described_class.value_type(Group, "primary_group_id")).to eq(Integer)
9+
expect(described_class.value_type(Group, "primary", "name")).to eq(String)
10+
expect(described_class.value_type(Group, "primary", "group_id")).to eq(Integer)
1111
end
1212

13-
it "returns nil when the method is not defined" do
14-
expect(described_class.value_type(Group, "not_a_real_method")).to be_nil
13+
it "returns nil when the attribute is not present in the named instance data" do
14+
expect(described_class.value_type(Group, "primary", "not_a_real_attribute")).to be_nil
1515
end
1616

17-
it "does not call the database for finder methods" do
18-
# Sanity check: this confirms we are calling literal-returning helpers,
19-
# not finder methods. Calling Group.primary would hit the DB; we should
20-
# never invoke value_type on it.
17+
it "returns nil when the named instance does not exist" do
18+
expect(described_class.value_type(Group, "not_a_real_instance", "name")).to be_nil
19+
end
20+
21+
it "does not invoke the generated helper methods" do
22+
# The generated method may be wrapped (e.g. deprecated) to raise, so we
23+
# must read the value from the data file rather than calling the method.
2124
expect(Group).not_to receive(:primary)
22-
described_class.value_type(Group, "primary_name")
25+
expect(Group).not_to receive(:primary_name)
26+
described_class.value_type(Group, "primary", "name")
2327
end
2428
end
2529

0 commit comments

Comments
 (0)