Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions doc/creating_commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ def adapter
end
```

#### Deprecating fields
#### Deprecating and replacing fields
To deprecate a field, add `:deprecated => true` as an option for the field. This will print a warning message to stderr whenever the field is displayed. Consider removing this field from the default set so it is not displayed without a `--fields` param:

```
Expand All @@ -770,18 +770,22 @@ Warning: Field 'Deprecated field' is deprecated and may be removed in future ver
Deprecated field: bar
```

Additionally, a field may be 'replaced by' another field using `:replaced_by => "Path/To/New/Field"`. This will mark the field as deprecated and print a similar warning message to stderr whenever the field is displayed:
Additionally, a field may be 'replaced by' another field using `:replaced_by_path => ["relative","path","to","new","field"]`. Use "!p" to indicate the parent field/list/collection and other strings to indicate the id of child field/list/collections. This will mark the field as deprecated and print a similar warning message to stderr whenever the field is displayed.

For example, to replace 'Foo/Bar/Old field' with 'Foo/Baz/New field', do the following:

```
field :rep_fld, _("Replaced field"), Fields::Field, :sets => ['ALL'], :replaced_by => "Path/New field"
field :old_fld, _("Old Field"), Fields::Field, :sets => ['ALL'], :replaced_by => ["!p","!p","baz","new_fld"]
```

Example output:

```
$ hammer foo info --fields "Replaced field"
Warning: Field 'Replaced field' is deprecated. Consider using 'Path/New field' instead.
Replaced field: bar
$ hammer foo info --fields "Foo/Bar/Old field"
Warning: Field 'Foo/Bar/Old field' is deprecated. Consider using 'Foo/Baz/New field' instead.
Foo:
Bar:
Old field: data
```

#### Verbosity
Expand Down
34 changes: 29 additions & 5 deletions lib/hammer_cli/output/adapter/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,7 @@ def render_fields(fields, data)
end

def render_field(field, data, label_width)
if field.replaced_by
warn _("Warning: Field '%{field}' is deprecated. Consider using '%{replacement}' instead.") % { field: field.full_label, replacement: field.replaced_by }
elsif field.deprecated
warn _("Warning: Field '%{field}' is deprecated and may be removed in future versions.") % { field: field.full_label }
end
warn_deprecated_field(field)

if field.is_a? Fields::ContainerField
output = ""
Expand Down Expand Up @@ -94,6 +90,34 @@ def label_width(fields)
end
end

# Print warnings to stderr for deprecated or replaced fields.
def warn_deprecated_field(field)
new_path = nil
if field.replaced_by_path
new_path = resolve_full_label_from_path(field, field.replaced_by_path)
end

if new_path
warn _("Warning: Field '%{field}' is deprecated. Consider using '%{replacement}' instead.") % { field: field.full_label, replacement: new_path }
elsif field.deprecated
warn _("Warning: Field '%{field}' is deprecated and may be removed in future versions.") % { field: field.full_label }
end
end

# Returns the full label (translated) for a replaced field given a array of steps relative to the replacement field.
# Use "!p" to go up one level in the hierarchy. If the field is not found, this method returns nil.
def resolve_full_label_from_path(field, steps)
current = field
steps.each do |step|
if step == "!p"
current = current.parent
else
current = current.fields.find { |f| f.id.to_s == step }
end
return nil unless current
end
current.full_label
end
end

HammerCLI::Output::Output.register_adapter(:base, Base)
Expand Down
6 changes: 3 additions & 3 deletions lib/hammer_cli/output/fields.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ module Fields
class Field
attr_reader :path
attr_writer :sets
attr_accessor :label, :parent, :replaced_by, :deprecated
attr_accessor :label, :parent, :replaced_by_path, :deprecated

def initialize(options={})
@hide_blank = options[:hide_blank].nil? ? false : options[:hide_blank]
@hide_missing = options[:hide_missing].nil? ? true : options[:hide_missing]
@path = options[:path] || []
@label = options[:label]
@sets = options[:sets]
@replaced_by = options[:replaced_by]
@deprecated = (options[:deprecated].nil?) ? !@replaced_by.nil? : options[:deprecated]
@replaced_by_path = options[:replaced_by_path]
@deprecated = (options[:deprecated].nil?) ? !@replaced_by_path.nil? : options[:deprecated]
@options = options
end

Expand Down
26 changes: 13 additions & 13 deletions test/unit/output/adapter/base_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
let(:login) { Fields::Field.new(:path => [:login], :label => "Login") }
let(:missing) { Fields::Field.new(:path => [:login], :label => "Missing", :hide_missing => false) }
let (:deprecated_a) { Fields::Field.new(:path => [:deprecated_a], :label => "Deprecated", :deprecated => true) }
let (:new_field) { Fields::Field.new(:path => [:new_field], :label => "New field") }
let (:deprecated_b) { Fields::Field.new(:path => [:deprecated_b], :label => "Replaced by", :replaced_by => 'New field') }
let (:deprecated_b) { Fields::Field.new(:path => [:deprecated_b], :label => "Replaced by", :replaced_by_path => ["!p", "New field"]) }

let(:data) { HammerCLI::Output::RecordCollection.new [{
:id => 112,
Expand Down Expand Up @@ -59,9 +58,8 @@
:value => '32'
}
],
deprecated_a: 'deprecated_a',
deprecated_b: 'deprecated_b',
new_field: 'new_field'
:deprecated_a => 'deprecated_a',
:deprecated_b => 'deprecated_b'
}]}

it "should print one field" do
Expand Down Expand Up @@ -218,16 +216,18 @@
end

it "should warn about replaced fields" do
fields = [new_field, deprecated_b]
fields = [deprecated_b]

expected_stdout= [
"New field: new_field",
"Replaced by: deprecated_b",
"\n"
].join("\n")
expected_stderr = "Warning: Field 'Replaced by' is deprecated. Consider using 'New field' instead.\n"
# Stubbing because parent/child relationship is not set up; covered in other tests
adapter.stub(:resolve_full_label_from_path, "Parent field/New field") do
expected_stdout= [
"Replaced by: deprecated_b",
"\n"
].join("\n")
expected_stderr = "Warning: Field 'Replaced by' is deprecated. Consider using 'Parent field/New field' instead.\n"

_{ adapter.print_collection(fields, data) }.must_output(stdout=expected_stdout, stderr=expected_stderr)
_{ adapter.print_collection(fields, data) }.must_output(stdout=expected_stdout, stderr=expected_stderr)
end
end

context 'printing by chunks' do
Expand Down