Skip to content

Commit 1be075d

Browse files
committed
Add support for custom validation contexts in resource creation and update
1 parent 67be954 commit 1be075d

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
@@ -58,7 +58,7 @@ def create
5858
contextualize_resource(resource)
5959
end
6060

61-
if resource.save
61+
if resource.save(context: validation_contexts_on_create(resource))
6262
yield(resource) if block_given?
6363
redirect_to(
6464
after_resource_created_path(resource),
@@ -74,7 +74,9 @@ def create
7474
end
7575

7676
def update
77-
if requested_resource.update(resource_params)
77+
requested_resource.assign_attributes(resource_params)
78+
79+
if requested_resource.save(context: validation_contexts_on_update(requested_resource))
7880
redirect_to(
7981
after_resource_updated_path(requested_resource),
8082
notice: translate_with_resource("update.success"),
@@ -341,6 +343,26 @@ def authorize_resource(resource)
341343
def contextualize_resource(resource)
342344
end
343345

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