Skip to content

Commit

Permalink
Raise a helpful error for missing dashboard attrs
Browse files Browse the repository at this point in the history
Closes #246

Problem:

If an attribute is missing from a dashboard's `ATTRIBUTE_TYPES` hash,
the user will see a generic error
when they visit a dashboard page that tries to display that attribute.

The error is:

```
NoMethodError: undefined method new for `nil:NilClass` in `Page::Base`
```

Solution:

Add accessor methods to `BaseDashboard`
for fetching attributes from the dashboard.
If a requested attribute is not present,
the accessor methods raise a helpful error message.
  • Loading branch information
5minpause authored and c-lliope committed Nov 19, 2015
1 parent 7403023 commit d212265
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

### Upcoming Release

* [#251] [FEATURE] Raise a helpful error when an attribute is missing from
`ATTRIBUTE_TYPES`
* [#247] [BUGFIX] Populate `has_many` and `belongs_to` select boxes
with the current value of the relationship.
* [#237] [I18n] Fix broken paths for several I18n files (de, es, fr, pt-BR, vi).
Expand Down
18 changes: 18 additions & 0 deletions lib/administrate/base_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ def attribute_types
self.class::ATTRIBUTE_TYPES
end

def attribute_type_for(attribute_name)
attribute_types.fetch(attribute_name) do
fail attribute_not_found_message(attribute_name)
end
end

def attribute_types_for(attribute_names)
attribute_names.each_with_object({}) do |name, attributes|
attributes[name] = attribute_type_for(name)
end
end

def form_attributes
self.class::FORM_ATTRIBUTES
end
Expand All @@ -39,5 +51,11 @@ def collection_attributes
def display_resource(resource)
"#{resource.class} ##{resource.id}"
end

private

def attribute_not_found_message(attr)
"Attribute #{attr} could not be found in #{self.class}::ATTRIBUTE_TYPES"
end
end
end
6 changes: 2 additions & 4 deletions lib/administrate/page/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,8 @@ def resource_name

def attribute_field(dashboard, resource, attribute_name, page)
value = get_attribute_value(resource, attribute_name)

dashboard.
attribute_types[attribute_name].
new(attribute_name, value, page)
field = dashboard.attribute_type_for(attribute_name)
field.new(attribute_name, value, page)
end

def get_attribute_value(resource, attribute_name)
Expand Down
2 changes: 1 addition & 1 deletion lib/administrate/page/collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def attributes_for(resource)
end

def attribute_types
dashboard.attribute_types.slice(*attribute_names)
dashboard.attribute_types_for(attribute_names)
end

def ordered_html_class(attr)
Expand Down
43 changes: 43 additions & 0 deletions spec/dashboards/customer_dashboard_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,49 @@
end
end

def missing_attribute_message(attribute, dashboard_class)
"Attribute #{attribute} could not be found in #{dashboard_class}::ATTRIBUTE_TYPES"
end

describe "#attribute_type_for" do
context "for an existing attribute" do
it "returns the attribute field" do
dashboard = CustomerDashboard.new
field = dashboard.attribute_type_for(:name)
expect(field).to eq Administrate::Field::String
end
end

context "for a non-existent attribute" do
it "raises an exception" do
dashboard = CustomerDashboard.new
expect { dashboard.attribute_type_for(:foo) }.
to raise_error missing_attribute_message("foo", "CustomerDashboard")
end
end
end

describe "#attribute_types_for" do
context "for existing attributes" do
it "returns the attribute fields" do
dashboard = CustomerDashboard.new
fields = dashboard.attribute_types_for([:name, :email])
expect(fields).to match(
name: Administrate::Field::String,
email: Administrate::Field::Email,
)
end
end

context "for one non-existent attribute" do
it "raises an exception" do
dashboard = CustomerDashboard.new
expect { dashboard.attribute_types_for([:name, :foo]) }.
to raise_error missing_attribute_message("foo", "CustomerDashboard")
end
end
end

describe "#display_resource" do
it "returns the customer's name" do
customer = double(name: "Example Customer")
Expand Down

0 comments on commit d212265

Please sign in to comment.