diff --git a/CHANGELOG b/CHANGELOG index 602a28a18..bc28e68ef 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === master +* Add inspect_pk plugin to make it easier to retrieve model instance based on inspect output (jeremyevans) + * Treat all Trilogy errors with error code 1205 as Sequel::DatabaseLockTimeout in the trilogy adapter (jeremyevans) * Allow Data{base,set}#extension to not require files if the extension is already registered (jeremyevans) (#2246) diff --git a/lib/sequel/model/base.rb b/lib/sequel/model/base.rb index 1b57a183e..f108308da 100644 --- a/lib/sequel/model/base.rb +++ b/lib/sequel/model/base.rb @@ -1311,7 +1311,7 @@ def id # Returns a string representation of the model instance including # the class name and values. def inspect - "#<#{model.name} @values=#{inspect_values}>" + "#<#{inspect_prefix} @values=#{inspect_values}>" end # Returns the keys in +values+. May not include all column names. @@ -1994,7 +1994,12 @@ def initialize_set(h) set(h) unless h.empty? end - # Default inspection output for the values hash, overwrite to change what #inspect displays. + # Default inspect output for the inspect, by default, just showing the class. + def inspect_prefix + model.name + end + + # Default inspect output for the values hash, overwrite to change what #inspect displays. def inspect_values @values.inspect end diff --git a/lib/sequel/plugins/inspect_pk.rb b/lib/sequel/plugins/inspect_pk.rb new file mode 100644 index 000000000..4a0bea313 --- /dev/null +++ b/lib/sequel/plugins/inspect_pk.rb @@ -0,0 +1,44 @@ +# frozen-string-literal: true + +module Sequel + module Plugins + # The inspect_pk plugin includes the pk right next to the + # model name in inspect, allowing for easily copying and + # pasting to retrieve a copy of the object: + # + # Album.with_pk(1).inspect + # # default: # + # # with inspect_pk: # + # + # Usage: + # + # # Make all model instances include pk in inspect output + # Sequel::Model.plugin :inspect_pk + # + # # Make Album instances include pk in inspect output + # Album.plugin :inspect_pk + module InspectPk + module InstanceMethods + private + + # The primary key value to include in the inspect output, if any. + # For composite primary keys, this only includes a value if all + # fields are present. + def inspect_pk + if primary_key && (pk = self.pk) && (!(Array === pk) || pk.all?) + pk + end + end + + # Include the instance's primary key in the output. + def inspect_prefix + if v = inspect_pk + "#{super}[#{v.inspect}]" + else + super + end + end + end + end + end +end diff --git a/spec/extensions/inspect_pk_spec.rb b/spec/extensions/inspect_pk_spec.rb new file mode 100644 index 000000000..6a8367be1 --- /dev/null +++ b/spec/extensions/inspect_pk_spec.rb @@ -0,0 +1,45 @@ +require_relative "spec_helper" + +describe "inspect_pk plugin" do + def inspect(vals={}, &block) + Class.new(Sequel::Model) do + def self.name; 'M' end + plugin :inspect_pk + set_dataset DB.dataset + class_exec(&block) if block + columns(*vals.keys) + unrestrict_primary_key + end.new(vals).inspect + end + + it "should not include primary key value if model does not have primary key" do + inspect(id: 1){no_primary_key}.must_equal "#1}.inspect}>" + end + + it "should not include primary key value if model has scalar primary key and instance does not have primary key value" do + inspect{set_primary_key :id}.must_equal "#" + end + + it "should not include primary key value if model instance has composite primary key and instance does not have values for all primary key components" do + [{id1: 1, id2: nil}, {id1: nil, id2: 2}, {id1: nil, id2: nil}].each do |vals| + inspect(vals){set_primary_key [:id1, :id2]}.must_equal "#" + end + end + + it "should include primary value for scalar primary key if present" do + inspect(id: 1){set_primary_key :id}.must_equal "#" + end + + it "should include primary value for composite primary key if all fields present" do + vals = {id1: 1, id2: 2} + inspect(vals){set_primary_key [:id1, :id2]}.must_equal "#" + end + + it "should use inspect value of primary key" do + inspect(id: "1"){}.must_equal "#" + end + + it "should use inspect_pk method to get inspect pk value" do + inspect{def inspect_pk; "2" end}.must_equal "#" + end +end diff --git a/www/pages/plugins.html.erb b/www/pages/plugins.html.erb index 0dec07467..2abc78602 100644 --- a/www/pages/plugins.html.erb +++ b/www/pages/plugins.html.erb @@ -455,6 +455,10 @@ Adds Model.finder and Model.prepared_finder methods for defining optimized lookup methods.
  • +inspect_pk +Makes it easier to retrieve model instance based on inspect output. +
  • +
  • list Allows you to treat model objects as being part of a list, so you can move them up/down and get next/previous entries.