From 8e8cfa6c52ff8fc2a655b768db5baafed40c1a2d Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 19 Sep 2017 15:20:01 +0200 Subject: Add `ModelAttribute` This new class will allow us to generate a list of all editable fields in all our models including the type of each field. We need this for Compliance Control, in order to get a list of fields or models & fields that can be selected to validate a given model validation check. The crucial bits here are the models, fields, and the types of those fields. These need to be defined (manually at least to begin with), accessible, and filterable. Refs #4401 --- spec/lib/model_attribute_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 spec/lib/model_attribute_spec.rb (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb new file mode 100644 index 000000000..88d3997b6 --- /dev/null +++ b/spec/lib/model_attribute_spec.rb @@ -0,0 +1,16 @@ +RSpec.describe ModelAttribute do + describe ".define" do + it "adds a new instance of ModelAttribute to @@all" do + ModelAttribute.define(:route, :name, :string) + + expect(ModelAttribute.all.length).to eq(1) + + model_attr = ModelAttribute.all.first + + expect(model_attr).to be_an_instance_of(ModelAttribute) + expect(model_attr.klass).to eq(:route) + expect(model_attr.name).to eq(:name) + expect(model_attr.data_type).to eq(:string) + end + end +end -- cgit v1.2.3 From 2f555897bff3f8fa6dd5e9e0c6d48f0073edc349 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 19 Sep 2017 15:39:37 +0200 Subject: ModelAttribute spec: Allow test to handle existing elements in `@@all` When `ModelAttribute` instances are added to `@@all` directly in the class, the test breaks. Make it a little more robust by checking change in array size instead of total size. Refs #4401 --- spec/lib/model_attribute_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index 88d3997b6..da767cfed 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -1,11 +1,11 @@ RSpec.describe ModelAttribute do describe ".define" do it "adds a new instance of ModelAttribute to @@all" do - ModelAttribute.define(:route, :name, :string) + expect do + ModelAttribute.define(:route, :name, :string) + end.to change { ModelAttribute.all.length }.by(1) - expect(ModelAttribute.all.length).to eq(1) - - model_attr = ModelAttribute.all.first + model_attr = ModelAttribute.all.last expect(model_attr).to be_an_instance_of(ModelAttribute) expect(model_attr.klass).to eq(:route) -- cgit v1.2.3 From e1547b52a372942b34cda3b3fee4ab76e9f1b65e Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 19 Sep 2017 16:59:45 +0200 Subject: ModelAttribute: Add `#code` method A method that returns a string representation of the attribute, in the form `:class#:name". This will be used to store a reference to the attribute in the database. For example, a validation will reference a `ModelAttribute` in a database column using this `#code` string. Refs #4401 --- spec/lib/model_attribute_spec.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index da767cfed..ad1dd863f 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -13,4 +13,12 @@ RSpec.describe ModelAttribute do expect(model_attr.data_type).to eq(:string) end end + + describe "#code" do + it "returns a string representation of the attribute" do + model_attr = ModelAttribute.new(:route, :name, :string) + + expect(model_attr.code).to eq('route#name') + end + end end -- cgit v1.2.3 From a60bf813aa118648998093242d6db0e1d8613e76 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 19 Sep 2017 18:13:20 +0200 Subject: ModelAttribute: Add `.methods_by_class` method Allows us to get all `ModelAttribute`s given a certain class name. Needed an `#==` method to be able to test object equality more easily so I added one in. I don't like that the `klass` is a lowercase symbol and the `klass` attribute to `.methods_by_class` is a constantized string. Want to correct that and make them uniform. Only did it this way because that's how it was suggested in the ticket. Refs #4401 --- spec/lib/model_attribute_spec.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index ad1dd863f..73114ae1e 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -14,6 +14,23 @@ RSpec.describe ModelAttribute do end end + describe ".methods_by_class" do + it "returns all ModelAttributes for a given class" do + ModelAttribute.instance_variable_set(:@__all__, [ + ModelAttribute.new(:route, :name, :string), + ModelAttribute.new(:route, :published_name, :string), + ModelAttribute.new(:route, :direction, :string), + ModelAttribute.new(:journey_pattern, :name, :string) + ]) + + expect(ModelAttribute.methods_by_class('Route')).to match_array([ + ModelAttribute.new(:route, :name, :string), + ModelAttribute.new(:route, :published_name, :string), + ModelAttribute.new(:route, :direction, :string) + ]) + end + end + describe "#code" do it "returns a string representation of the attribute" do model_attr = ModelAttribute.new(:route, :name, :string) @@ -21,4 +38,13 @@ RSpec.describe ModelAttribute do expect(model_attr.code).to eq('route#name') end end + + describe "#==" do + it "returns true when :klass, :name, and :data_type attributes match" do + route_name = ModelAttribute.new(:route, :name, :string) + other_route_name = ModelAttribute.new(:route, :name, :string) + + expect(route_name == other_route_name).to be true + end + end end -- cgit v1.2.3 From 5b437302c3cbc90f920de11169f249658c23a5ee Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Tue, 19 Sep 2017 18:16:16 +0200 Subject: ModelAttribute.methods_by_class: Take symbol parameter instead of string Didn't like how `#initialize` takes a different type for `klass` than `.methods_by_class`. Make these types and values uniform. If we need to change it, we should make a separate mechanism to do so. I think. Refs #4401 --- spec/lib/model_attribute_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index 73114ae1e..8463d12fe 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -23,7 +23,7 @@ RSpec.describe ModelAttribute do ModelAttribute.new(:journey_pattern, :name, :string) ]) - expect(ModelAttribute.methods_by_class('Route')).to match_array([ + expect(ModelAttribute.methods_by_class(:route)).to match_array([ ModelAttribute.new(:route, :name, :string), ModelAttribute.new(:route, :published_name, :string), ModelAttribute.new(:route, :direction, :string) -- cgit v1.2.3 From 198659b133aba39cdd92d37fd3b93a223159994b Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 22 Sep 2017 12:05:10 +0200 Subject: ModelAttribute spec: Rename `@@all` In c9a997f337c9b45f62b50629de96fa95f20c1a7f, we changed the storage mechanism of `all` and made it not a class method. Update the spec description to reflect this. Refs #4401 --- spec/lib/model_attribute_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index 8463d12fe..2da178d2c 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -1,6 +1,6 @@ RSpec.describe ModelAttribute do describe ".define" do - it "adds a new instance of ModelAttribute to @@all" do + it "adds a new instance of ModelAttribute to .all" do expect do ModelAttribute.define(:route, :name, :string) end.to change { ModelAttribute.all.length }.by(1) -- cgit v1.2.3 From 9179af1df905ff9980228d2aa0ba77418f2781aa Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 22 Sep 2017 12:11:41 +0200 Subject: ModelAttribute: Add `.methods_by_class_and_type` method This enables filtering by class like `.methods_by_class` and additionally only selecting attributes matching a certain data type. Refs #4401 --- spec/lib/model_attribute_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index 2da178d2c..faea0b483 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -31,6 +31,21 @@ RSpec.describe ModelAttribute do end end + describe ".methods_by_class_and_type" do + it "returns ModelAttributes of a certain class and type" do + ModelAttribute.instance_variable_set(:@__all__, [ + ModelAttribute.new(:route, :name, :string), + ModelAttribute.new(:route, :checked_at, :date), + ModelAttribute.new(:journey_pattern, :name, :string), + ModelAttribute.new(:journey_pattern, :section_status, :integer) + ]) + + expect(ModelAttribute.methods_by_class_and_type(:route, :string)).to match_array([ + ModelAttribute.new(:route, :name, :string) + ]) + end + end + describe "#code" do it "returns a string representation of the attribute" do model_attr = ModelAttribute.new(:route, :name, :string) -- cgit v1.2.3 From 404b143af9ed49912e1e0065c832639188aa87de Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 22 Sep 2017 12:25:36 +0200 Subject: ModelAttribute: Add `.classes` method This allows people to get a list of the classes defined in `ModelAttribute`. The classes are turned into constant-cased strings. Not sure if that's useful, but this is how it was described in the ticket. Refs #4401 --- spec/lib/model_attribute_spec.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index faea0b483..9e10bf40f 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -14,6 +14,22 @@ RSpec.describe ModelAttribute do end end + describe ".classes" do + it "returns the list of classes of ModelAttributes in .all" do + ModelAttribute.instance_variable_set(:@__all__, [ + ModelAttribute.new(:route, :name, :string), + ModelAttribute.new(:journey_pattern, :name, :string), + ModelAttribute.new(:time_table, :start_date, :date) + ]) + + expect(ModelAttribute.classes).to match_array([ + 'Route', + 'JourneyPattern', + 'TimeTable' + ]) + end + end + describe ".methods_by_class" do it "returns all ModelAttributes for a given class" do ModelAttribute.instance_variable_set(:@__all__, [ -- cgit v1.2.3 From 9086e4c7d253927e7fad07bcd4eb194eeff393ca Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 22 Sep 2017 12:42:41 +0200 Subject: ModelAttribute: Add `.group_by_class` method This returns all defined `ModelAttribute`s as a hash of class keys containing lists of the attributes they contain. Refs #4401 --- spec/lib/model_attribute_spec.rb | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index 9e10bf40f..0ca90430f 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -30,6 +30,30 @@ RSpec.describe ModelAttribute do end end + describe ".group_by_class" do + it "returns all ModelAttributes grouped by klass" do + ModelAttribute.instance_variable_set(:@__all__, [ + ModelAttribute.new(:route, :name, :string), + ModelAttribute.new(:route, :published_name, :string), + ModelAttribute.new(:journey_pattern, :name, :string), + ModelAttribute.new(:vehicle_journey, :number, :integer) + ]) + + expect(ModelAttribute.group_by_class).to eq({ + route: [ + ModelAttribute.new(:route, :name, :string), + ModelAttribute.new(:route, :published_name, :string), + ], + journey_pattern: [ + ModelAttribute.new(:journey_pattern, :name, :string), + ], + vehicle_journey: [ + ModelAttribute.new(:vehicle_journey, :number, :integer) + ] + }) + end + end + describe ".methods_by_class" do it "returns all ModelAttributes for a given class" do ModelAttribute.instance_variable_set(:@__all__, [ -- cgit v1.2.3 From 2d7ce83439f29d261f0c5ec05140359218cfe661 Mon Sep 17 00:00:00 2001 From: Teddy Wing Date: Fri, 22 Sep 2017 14:10:45 +0200 Subject: ModelAttribute: Add `#from_code` method Enables finding a `ModelAttribute` by a string code combining klass and name. Refs #4401 --- spec/lib/model_attribute_spec.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'spec/lib/model_attribute_spec.rb') diff --git a/spec/lib/model_attribute_spec.rb b/spec/lib/model_attribute_spec.rb index 0ca90430f..427e01490 100644 --- a/spec/lib/model_attribute_spec.rb +++ b/spec/lib/model_attribute_spec.rb @@ -30,6 +30,18 @@ RSpec.describe ModelAttribute do end end + describe ".from_code" do + it "returns a ModelAttribute from a given code" do + ModelAttribute.instance_variable_set(:@__all__, [ + ModelAttribute.new(:journey_pattern, :name, :string) + ]) + + expect(ModelAttribute.from_code('journey_pattern#name')).to eq( + ModelAttribute.new(:journey_pattern, :name, :string) + ) + end + end + describe ".group_by_class" do it "returns all ModelAttributes grouped by klass" do ModelAttribute.instance_variable_set(:@__all__, [ -- cgit v1.2.3