Skip to content

Commit bce9735

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

File tree

3 files changed

+92
-2
lines changed

3 files changed

+92
-2
lines changed

app/controllers/administrate/application_controller.rb

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def create
4545
resource = new_resource(resource_params)
4646
authorize_resource(resource)
4747

48-
if resource.save
48+
if resource.save(context: validation_contexts_on_create(resource))
4949
yield(resource) if block_given?
5050
redirect_to(
5151
after_resource_created_path(resource),
@@ -59,7 +59,9 @@ def create
5959
end
6060

6161
def update
62-
if requested_resource.update(resource_params)
62+
requested_resource.assign_attributes(resource_params)
63+
64+
if requested_resource.save(context: validation_contexts_on_update(requested_resource))
6365
redirect_to(
6466
after_resource_updated_path(requested_resource),
6567
notice: translate_with_resource("update.success"),
@@ -272,6 +274,33 @@ def authorize_resource(resource)
272274
end
273275
end
274276

277+
# Override this if you want to contextualize the resource differently.
278+
#
279+
# @param resource A resource to be contextualized.
280+
# @return nothing
281+
def contextualize_resource(resource)
282+
end
283+
284+
# Override this if you want to provide additional validation contexts.
285+
#
286+
# @param resource [ActiveRecord::Base] The resource to be validated.
287+
# @return [Array<Symbol>] The validation contexts to be used.
288+
def validation_contexts_on_create(resource)
289+
default_validation_contexts(resource)
290+
end
291+
292+
# Override this if you want to provide additional validation contexts.
293+
#
294+
# @param resource [ActiveRecord::Base] The resource to be validated.
295+
# @return [Array<Symbol>] The validation contexts to be used.
296+
def validation_contexts_on_update(resource)
297+
default_validation_contexts(resource)
298+
end
299+
300+
def default_validation_contexts(resource)
301+
resource.new_record? ? [:create] : [:update]
302+
end
303+
275304
def paginate_resources(resources)
276305
resources.page(params[:_page]).per(records_per_page)
277306
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)