Skip to content

Commit 88e5ecb

Browse files
committed
Add support for custom validation contexts in resource creation and update
1 parent 9cae2ff commit 88e5ecb

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
@@ -55,7 +55,7 @@ def create
5555
contextualize_resource(resource)
5656
end
5757

58-
if resource.save
58+
if resource.save(context: validation_contexts_on_create(resource))
5959
yield(resource) if block_given?
6060
redirect_to(
6161
after_resource_created_path(resource),
@@ -71,7 +71,9 @@ def create
7171
end
7272

7373
def update
74-
if requested_resource.update(resource_params)
74+
requested_resource.assign_attributes(resource_params)
75+
76+
if requested_resource.save(context: validation_contexts_on_update(requested_resource))
7577
redirect_to(
7678
after_resource_updated_path(requested_resource),
7779
notice: translate_with_resource("update.success"),
@@ -337,6 +339,26 @@ def authorize_resource(resource)
337339
def contextualize_resource(resource)
338340
end
339341

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