Skip to content

Commit f384038

Browse files
authored
Allow scope to accept field in Field::BelongsTo (#2652)
Sometimes, you need to query dependent fields on a resources' state, field, etc in forms. Previously, we would need to do something like this, which is confusing: ATTRIBUTE_TYPES = { customer_id: Field::Select.with_option(collection: ->(field) { Customer.some_scope.where(column: field.resource.column) }), customer: Field::BelongsTo } COLLECTION_ATTRIBUTES = [:customer] FORM_ATTRIBUTES = [:customer_id] Instead, this means we can do this: ATTRIBUTE_TYPES = { customer: Field::BelongsTo.with_option(scope: ->(field) { Customer.some_scope.where(column: field.resource.column) }), } COLLECTION_ATTRIBUTES = [:customer] FORM_ATTRIBUTES = [:customer] Closes #2459
1 parent b7aa546 commit f384038

File tree

3 files changed

+26
-3
lines changed

3 files changed

+26
-3
lines changed

docs/customizing_dashboards.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ the table views and in the dropdown menu on the record forms.
8282
You can set multiple columns as well with direction. E.g.: `"name, email DESC"`.
8383

8484
`:scope` - Specifies a custom scope inside a callable. Useful for preloading.
85-
Example: `.with_options(scope: -> { MyModel.includes(:rel).limit(5) })`
85+
Example #1: `.with_options(scope: -> { MyModel.includes(:rel).limit(5) })`
86+
Example #2: `.with_options(scope: -> (field) { field.resource.my_models.includes(:rel).limit(5) })`
8687

8788
`:include_blank` - Specifies if the select element to be rendered should include
8889
blank option. Default is `true`.
@@ -113,7 +114,7 @@ association `belongs_to :country`, from your model.
113114

114115
**Field::HasMany**
115116

116-
`:collection_attributes` - Set the columns to display in the show view.
117+
`:collection_attributes` - Set the columns to display in the show view.
117118
Default is COLLECTION_ATTRIBUTES in dashboard.
118119

119120
`:limit` - The number of resources (paginated) to display in the show view. To disable pagination,

lib/administrate/field/belongs_to.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ def include_blank_option
4141
private
4242

4343
def candidate_resources
44-
scope = options[:scope] ? options[:scope].call : associated_class.all
44+
scope =
45+
if options[:scope]
46+
options[:scope].arity.positive? ? options[:scope].call(self) : options[:scope].call
47+
else
48+
associated_class.all
49+
end
4550

4651
order = options.delete(:order)
4752
order ? scope.reorder(order) : scope

spec/lib/fields/belongs_to_spec.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,23 @@
306306

307307
expect(resources).to eq ["customer-3", "customer-2"]
308308
end
309+
310+
context "when scope with argument" do
311+
it "returns the resources within the passed scope" do
312+
# Building instead of creating, to avoid a dependent customer being
313+
# created, leading to random failures
314+
order = build(:order)
315+
316+
1.upto(3) { |i| create :customer, name: "customer-#{i}" }
317+
scope = ->(_field) { Customer.order(name: :desc).limit(2) }
318+
319+
association = Administrate::Field::BelongsTo.with_options(scope: scope)
320+
field = association.new(:customer, [], :show, resource: order)
321+
resources = field.associated_resource_options.compact.to_h.keys
322+
323+
expect(resources).to eq ["customer-3", "customer-2"]
324+
end
325+
end
309326
end
310327
end
311328
end

0 commit comments

Comments
 (0)