Skip to content

Commit 593da9d

Browse files
committed
Some contribution to README
1 parent c9d040a commit 593da9d

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

README.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,65 @@ Obviously, you can construct your query as required for the use case the datatab
151151
__IMPORTANT:__ Make sure to return an `ActiveRecord::Relation` object as the end product of this method. Why? Because the result from
152152
this method, will be chained (for now) to `ActiveRecord` methods for sorting, filtering and pagination.
153153

154+
#### Associated and nested models
155+
The previous example has only one single model. But what about if you have some associated nested models and in a report you want to show fields from these tables.
156+
157+
Take an example that has an Event, Course, Coursetype, Allocation, Teacher, Contact, Competency and Competency_type models. We want to have a datatables report which has the following column:
158+
```ruby
159+
'coursetypes.name',
160+
'courses.name',
161+
'events.title',
162+
'events.event_start',
163+
'events.event_end',
164+
'contacts.full_name',
165+
'competency_types.name',
166+
'events.status'
167+
```
168+
We want to sort and search on all columns of the list. The related definition would be:
169+
```ruby
170+
171+
def sortable_columns
172+
@sortable_columns ||= [
173+
'coursetypes.name',
174+
'courses.name',
175+
'events.title',
176+
'events.event_start',
177+
'events.event_end',
178+
'contacts.last_name',
179+
'competency_types.name',
180+
'events.status'
181+
]
182+
end
183+
184+
def searchable_columns
185+
@searchable_columns ||= [
186+
'coursetypes.name',
187+
'courses.name',
188+
'events.title',
189+
'events.event_start',
190+
'events.event_end',
191+
'contacts.last_name',
192+
'competency_types.name',
193+
'events.status'
194+
]
195+
end
196+
197+
def get_raw_records
198+
Event.joins([{course: :coursetype}, {allocations: {teacher: [:contact, {competencies: :competency_type}]}} ]).distinct
199+
end
200+
```
201+
__Some comments for the above code:__
202+
1. In the list we show full_name, but in sortable_columns and searchable_columns we use last_name from the Contact model. The reason is we can use only database columns as sort or search fields and the full_name is not a database field.
203+
2. In the get_raw_records method we have quite a complex query having one to many and may to many associations using the joins ActiveRecord method. The joins will generate INNER JOIN relations in the SQL query. In this case we do not include all event in the report if we have events which is not associated with any model record from the relation.
204+
3. To have all event records in the list we should use the .includes method, which generate LEFT OUTER JOIN relation of the SQL query. __IMPORTANT:__ Make sure to append .references(:related_model) with any associated model. That forces the eager loading of all the associated models by one SQL query, and the search condition for any column works fine. Otherwise the :recordsFiltered => filter_records(get_raw_records).count(:all) will generate 2 SQL queries (one for the Event model, and then another for the associated tables). The :recordsFiltered => filter_records(get_raw_records).count(:all) will use only the first one to return from the ActiveRecord::Relation object in get_raw_records and you will get an error message of __Unknown column 'yourtable.yourfield' in 'where clause'__ in case the search field value is not empty.
205+
206+
So the query with includes() method is:
207+
```
208+
def get_raw_records
209+
Event.includes([{course: :coursetype}, {allocations: {teacher: [:contact, {competencies: :competency_type}]}} ]).references(:course).distinct
210+
end
211+
```
212+
154213
### Controller
155214
Set up the controller to respond to JSON
156215

0 commit comments

Comments
 (0)