Skip to content

Commit 58219f1

Browse files
committed
Add support for custom validation contexts in resource creation and update
1 parent b8d4885 commit 58219f1

3 files changed

Lines changed: 92 additions & 2 deletions

File tree

app/controllers/administrate/application_controller.rb

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def create
4848
@resource = resource = new_resource(resource_params)
4949
authorize_resource(resource)
5050

51-
if resource.save
51+
if resource.save(context: validation_contexts_on_create(resource))
5252
yield(resource) if block_given?
5353
redirect_to(
5454
after_resource_created_path(resource),
@@ -63,7 +63,9 @@ def create
6363

6464
def update
6565
@resource = resource = requested_resource
66-
if resource.update(resource_params)
66+
resource.assign_attributes(resource_params)
67+
68+
if resource.save(context: validation_contexts_on_update(resource))
6769
redirect_to(
6870
after_resource_updated_path(resource),
6971
notice: translate_with_resource("update.success"),
@@ -277,6 +279,33 @@ def authorize_resource(resource)
277279
end
278280
end
279281

282+
# Override this if you want to contextualize the resource differently.
283+
#
284+
# @param resource A resource to be contextualized.
285+
# @return nothing
286+
def contextualize_resource(resource)
287+
end
288+
289+
# Override this if you want to provide additional validation contexts.
290+
#
291+
# @param resource [ActiveRecord::Base] The resource to be validated.
292+
# @return [Array<Symbol>] The validation contexts to be used.
293+
def validation_contexts_on_create(resource)
294+
default_validation_contexts(resource)
295+
end
296+
297+
# Override this if you want to provide additional validation contexts.
298+
#
299+
# @param resource [ActiveRecord::Base] The resource to be validated.
300+
# @return [Array<Symbol>] The validation contexts to be used.
301+
def validation_contexts_on_update(resource)
302+
default_validation_contexts(resource)
303+
end
304+
305+
def default_validation_contexts(resource)
306+
resource.new_record? ? [:create] : [:update]
307+
end
308+
280309
def paginate_resources(resources)
281310
resources.page(params[:_page]).per(records_per_page)
282311
end

docs/customizing_controller_actions.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,30 @@ def create
107107
end
108108
end
109109
```
110+
111+
## Validation Contexts
112+
113+
You can customize the context when saving a resource in the controller.
114+
For example, with the following settings, regular admins are required to input a name, but super admins can update the resource *without* a name.
115+
116+
```ruby
117+
# Model
118+
validates :name, presence: true, on: :save_by_regular_admin
119+
120+
# Controller
121+
def validation_contexts_on_create(resource)
122+
if current_user.super_admin?
123+
super + [:save_by_super_admin]
124+
else
125+
super + [:save_by_regular_admin]
126+
end
127+
end
128+
129+
def validation_contexts_on_update(resource)
130+
if current_user.super_admin?
131+
super + [:save_by_super_admin]
132+
else
133+
super + [:save_by_regular_admin]
134+
end
135+
end
136+
```

spec/controllers/admin/application_controller_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,38 @@ def authorized_action?(resource, _action)
100100
.to raise_error(Administrate::NotAuthorizedError)
101101
end
102102
end
103+
104+
describe "validation contexts" do
105+
render_views
106+
controller(Admin::ProductsController) do
107+
def validation_contexts_on_create(resource)
108+
super + [:some_unclear_situation]
109+
end
110+
111+
def validation_contexts_on_update(resource)
112+
super + [:some_unclear_situation]
113+
end
114+
end
115+
116+
context "on create" do
117+
it "raise a validation error due to custom validation context" do
118+
params = attributes_for(:product)
119+
post :create, params: {product: params}
120+
121+
expect(response).to have_http_status(:unprocessable_entity)
122+
expect(response.body).to include("Product meta tag can&#39;t be blank")
123+
end
124+
end
125+
126+
context "on update" do
127+
it "raise a validation error due to custom validation context" do
128+
product = create(:product, product_meta_tag: nil)
129+
params = {name: "New Name"}
130+
put :update, params: {id: product.to_param, product: params}
131+
132+
expect(response).to have_http_status(:unprocessable_entity)
133+
expect(response.body).to include("Product meta tag can&#39;t be blank")
134+
end
135+
end
136+
end
103137
end

0 commit comments

Comments
 (0)