Skip to content

Commit

Permalink
Support writers in Rails models
Browse files Browse the repository at this point in the history
For rails models with a 'foo' column, create pins for 'foo=' as
well as the existing 'foo' method.
  • Loading branch information
apiology committed Oct 14, 2024
1 parent 144cec0 commit 43cec61
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ jobs:
ruby-version:
- "3.1"
- "3.2"
- "3.3"
solargraph-version:
- "0.48.0"
- "0.49.0"
- "0.50.0"
fail-fast: false

steps:
Expand Down
10 changes: 10 additions & 0 deletions lib/solargraph/rails/annotate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ def process(source_map, ns)
location:
Solargraph::Location.new(source_map.filename, snip.range)
)

pins <<
Util.build_public_method(
ns,
"#{name}=",
types: [ruby_type],
params: { 'value' => [ruby_type] },
location:
Solargraph::Location.new(source_map.filename, snip.range)
)
end

pins
Expand Down
23 changes: 17 additions & 6 deletions lib/solargraph/rails/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,26 @@ def process(source_map, ns)

return [] unless table

pins =
table.map do |column, data|
pins = table.flat_map do |column, data|
ruby_type = RUBY_TYPES.fetch(data.type.to_sym)
location = Util.build_location(data.ast, 'db/schema.rb')

[
Util.build_public_method(
ns,
column,
types: [RUBY_TYPES.fetch(data.type.to_sym)],
location: Util.build_location(data.ast, 'db/schema.rb')
)
end
types: [ruby_type],
location: location
),
Util.build_public_method(
ns,
"#{column}=",
types: [ruby_type],
params: { 'value' => [ruby_type] },
location: location
),
]
end

if pins.any?
Solargraph.logger.debug(
Expand Down
19 changes: 18 additions & 1 deletion lib/solargraph/rails/util.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ def self.build_public_method(
ns,
name,
types: nil,
params: {},
location: nil,
attribute: false,
scope: :instance
Expand All @@ -18,11 +19,27 @@ def self.build_public_method(
}

comments = []
params.each do |name, types|
comments << "@param [#{types.join(',')}] #{name}"
end
comments << "@return [#{types.join(',')}]" if types

opts[:comments] = comments.join("\n")

Solargraph::Pin::Method.new(**opts)
m = Solargraph::Pin::Method.new(**opts)
parameters = params.map do |name, type|
Solargraph::Pin::Parameter.new(
location: nil,
closure: m,
comments: '',
name: name,
presence: nil,
decl: :arg,
asgn_code: nil
)
end
m.parameters.concat(parameters)
m
end

def self.build_module_include(ns, module_name, location)
Expand Down
10 changes: 9 additions & 1 deletion spec/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,19 @@ def use_workspace(folder, &block)
map
end

def assert_public_instance_method(map, query, return_type, &block)
def assert_public_instance_method(map, query, return_type, args: {}, &block)
pin = find_pin(query, map)
expect(pin).to_not be_nil
expect(pin.scope).to eq(:instance)
expect(pin.return_type.map(&:tag)).to eq(return_type)
args.each_pair do |name, type|
expect(parameter = pin.parameters.find { _1.name == name.to_s }).to_not be_nil
expect(parameter.return_type.tag).to eq(type)
end
pin.parameters.each do |param|
expect(args).to have_key(param.name.to_sym)
expect(param.return_type.tag).to eq(args[param.name.to_sym])
end

yield pin if block_given?
end
Expand Down
2 changes: 2 additions & 0 deletions spec/solargraph-rails/annotate_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class MyModel < ApplicationRecord
end

assert_public_instance_method(api_map, 'MyModel#start_date', ['Date'])
assert_public_instance_method(api_map, 'MyModel#start_date=', ['Date'],
args: { value: 'Date' })
assert_public_instance_method(
api_map,
'MyModel#living_expenses',
Expand Down
3 changes: 2 additions & 1 deletion spec/solargraph-rails/schema_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class Account < ActiveRecord::Base
end

assert_public_instance_method(map, "Account#balance", ["BigDecimal"])
assert_public_instance_method(map, "Account#balance=", ["BigDecimal"],
args: { value: 'BigDecimal' })
assert_public_instance_method(map, "Account#some_int", ["Integer"])
assert_public_instance_method(map, "Account#some_date", ["Date"])
assert_public_instance_method(map, "Account#some_big_id", ["Integer"])
Expand Down Expand Up @@ -129,4 +131,3 @@ class Invoice < ActiveRecord::Base
assert_public_instance_method(map, 'Invoice#amount', ['BigDecimal'])
end
end

0 comments on commit 43cec61

Please sign in to comment.