Skip to content

Commit a3ecb08

Browse files
committed
Add support for custom validation contexts in resource creation and update
1 parent 1c68b0e commit a3ecb08

File tree

3 files changed

+85
-2
lines changed

3 files changed

+85
-2
lines changed

app/controllers/administrate/application_controller.rb

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ def create
5656
contextualize_resource(resource)
5757
end
5858

59-
if resource.save
59+
if resource.save(context: validation_contexts_on_create(resource))
6060
yield(resource) if block_given?
6161
redirect_to(
6262
after_resource_created_path(resource),
@@ -72,7 +72,9 @@ def create
7272
end
7373

7474
def update
75-
if requested_resource.update(resource_params)
75+
requested_resource.assign_attributes(resource_params)
76+
77+
if requested_resource.save(context: validation_contexts_on_update(requested_resource))
7678
redirect_to(
7779
after_resource_updated_path(requested_resource),
7880
notice: translate_with_resource("update.success"),
@@ -339,6 +341,26 @@ def authorize_resource(resource)
339341
def contextualize_resource(resource)
340342
end
341343

344+
# Override this if you want to provide additional validation contexts.
345+
#
346+
# @param resource [ActiveRecord::Base] The resource to be validated.
347+
# @return [Array<Symbol>] The validation contexts to be used.
348+
def validation_contexts_on_create(resource)
349+
default_validation_contexts(resource)
350+
end
351+
352+
# Override this if you want to provide additional validation contexts.
353+
#
354+
# @param resource [ActiveRecord::Base] The resource to be validated.
355+
# @return [Array<Symbol>] The validation contexts to be used.
356+
def validation_contexts_on_update(resource)
357+
default_validation_contexts(resource)
358+
end
359+
360+
def default_validation_contexts(resource)
361+
resource.new_record? ? [:create] : [:update]
362+
end
363+
342364
def paginate_resources(resources)
343365
resources.page(params[:_page]).per(records_per_page)
344366
end

docs/customizing_controller_actions.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,30 @@ def create
125125
end
126126
end
127127
```
128+
129+
## Validation Contexts
130+
131+
You can customize the context when saving a resource in the controller.
132+
For example, with the following settings, regular admins are required to input a name, but super admins can update the resource *without* a name.
133+
134+
```ruby
135+
# Model
136+
validates :name, presence: true, on: :save_by_regular_admin
137+
138+
# Controller
139+
def validation_contexts_on_create(resource)
140+
if current_user.super_admin?
141+
super + [:save_by_super_admin]
142+
else
143+
super + [:save_by_regular_admin]
144+
end
145+
end
146+
147+
def validation_contexts_on_update(resource)
148+
if current_user.super_admin?
149+
super + [:save_by_super_admin]
150+
else
151+
super + [:save_by_regular_admin]
152+
end
153+
end
154+
```

spec/controllers/admin/application_controller_spec.rb

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,38 @@ def resource_resolver
234234
end
235235
end
236236
end
237+
238+
describe "validation contexts" do
239+
render_views
240+
controller(Admin::ProductsController) do
241+
def validation_contexts_on_create(resource)
242+
super + [:some_unclear_situation]
243+
end
244+
245+
def validation_contexts_on_update(resource)
246+
super + [:some_unclear_situation]
247+
end
248+
end
249+
250+
context "on create" do
251+
it "raise a validation error due to custom validation context" do
252+
params = attributes_for(:product)
253+
post :create, params: {product: params}
254+
255+
expect(response).to have_http_status(:unprocessable_entity)
256+
expect(response.body).to include("Product meta tag can&#39;t be blank")
257+
end
258+
end
259+
260+
context "on update" do
261+
it "raise a validation error due to custom validation context" do
262+
product = create(:product, product_meta_tag: nil)
263+
params = {name: "New Name"}
264+
put :update, params: {id: product.to_param, product: params}
265+
266+
expect(response).to have_http_status(:unprocessable_entity)
267+
expect(response.body).to include("Product meta tag can&#39;t be blank")
268+
end
269+
end
270+
end
237271
end

0 commit comments

Comments
 (0)