irie 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 70d0c4b896c361b3118094166c14bae9a734a530
4
+ data.tar.gz: ea3ff0813dabc51ba793191d92797f8c9f2b6704
5
+ SHA512:
6
+ metadata.gz: 9733f3a4277253428161f1c4b735832fbd5f53bf958b48236a90ec2a5249d143fe476d15814536126d3a690e47ef9fc5c53e6271af89dca314069837072acb62
7
+ data.tar.gz: c4b1a88c2571906e7378ee09a76409f2669dcd41e5402da6b55927881dfd33a9baf4e9bb248e6cbedd9dea7de921e05cceac16a6e0f56b17e8ac0ce9e4cdf7ba
data/README.md ADDED
@@ -0,0 +1,657 @@
1
+ [![Build Status](https://secure.travis-ci.org/FineLinePrototyping/irie.png?branch=master)][travis] [![Gem Version](https://badge.fury.io/rb/irie.png)][badgefury]
2
+
3
+ # Irie
4
+
5
+ Inherited Resources including extensions. Tested with Rails 4/edge, Inherited Resources 1.4/edge in Ruby 1.9.3, 2.0.0, and jruby-19mode.
6
+
7
+ Extend [Inherited Resources][inherited_resources] actions with the `extensions` method which provides symbolic references to do module includes as well as automatic inclusion of modules based on what actions are in-use. The included extensions provide more of a DSL-like way to define your controllers, and instead of model-heavy development via `scope` in models and `has_scope` in the controller, you can just define request parameter-based filters and their defaults in the controller. Also, ordering, parameter conversion, param value split delimiters, pagination, and more are supported.
8
+
9
+ ```ruby
10
+ class PostsController < ApplicationController
11
+
12
+ respond_to :json
13
+ inherit_resources
14
+
15
+ actions :index
16
+ extensions :count, :limit, :offset, :paging
17
+
18
+ can_filter_by :author, through: {author: :name}
19
+ default_filter_by :author, eq: 'anonymous'
20
+
21
+ can_filter_by :posted_on, using: [:lt, :eq, :gt]
22
+ default_filter_by :posted_on, gt: 1.year.ago
23
+
24
+ can_filter_by :company, through: {author: {company: :name}
25
+
26
+ can_order_by :posted_on, :author, :id
27
+ default_order_by {:posted_on => :desc}, :id
28
+
29
+ end
30
+ ```
31
+
32
+ Then set up your routes and any views.
33
+
34
+ Now here are some of the URLs you can hit:
35
+
36
+ ```
37
+ https://example.org/posts?author=John
38
+ https://example.org/posts?posted_on.gt=2012-08-08
39
+ https://example.org/posts?posted_on.gt=2012-08-08&count=
40
+ https://example.org/posts?company=Lipton
41
+ https://example.org/posts?page_count=
42
+ https://example.org/posts?page=1
43
+ https://example.org/posts?offset=30&limit=15
44
+ https://example.org/posts?order=author,-id
45
+ ```
46
+
47
+ You can also define a query to allow only admins to see private posts:
48
+
49
+ ```ruby
50
+ index_query ->(q) { @current_user.admin? ? q : q.where(:access => 'public') }
51
+ ```
52
+
53
+ and change the query depending on a supplied param:
54
+
55
+ ```ruby
56
+ can_filter_by_query \
57
+ status: ->(q, status) {
58
+ status == 'all' ? q : q.where(:status => status)
59
+ },
60
+ color: ->(q, color) {
61
+ if color == 'red'
62
+ q.where("color = 'red' or color = 'ruby'")
63
+ else
64
+ q.where(:color => color)
65
+ end
66
+ }
67
+ ```
68
+
69
+ Note: `extensions` also automatically includes common sets of extensions with certain actions. So, just specify `extensions` by itself can include things you can use, e.g.
70
+
71
+ ```ruby
72
+ class PostsController < ApplicationController
73
+ inherit_resources
74
+
75
+ actions :index
76
+ extensions
77
+ end
78
+ ```
79
+
80
+ ### Installation
81
+
82
+ In your Rails app's `Gemfile`:
83
+
84
+ ```ruby
85
+ gem 'irie'
86
+ ```
87
+
88
+ Then:
89
+
90
+
91
+ ```
92
+ bundle install
93
+ ```
94
+
95
+ ### Application Configuration
96
+
97
+ Each application-level configuration option can be configured one line at a time:
98
+
99
+ ```ruby
100
+ ::Irie.number_of_records_in_a_page = 30
101
+ ```
102
+
103
+ or in bulk, like:
104
+
105
+ ```ruby
106
+ ::Irie.configure do
107
+
108
+ # Default for :using in can_filter_by.
109
+ self.can_filter_by_default_using = [:eq]
110
+
111
+ # Use one or more alternate request parameter names for functions, e.g.
112
+ # `self.function_param_names = {distinct: :very_distinct, limit: [:limit, :limita]}`
113
+ self.function_param_names = {}
114
+
115
+ # Delimiter for ARel predicate in the request parameter name.
116
+ self.predicate_prefix = '.'
117
+
118
+ # You'd set this to false if id is used for something else other than primary key.
119
+ self.id_is_primary_key_param = true
120
+
121
+ # Used when paging is enabled.
122
+ self.number_of_records_in_a_page = 15
123
+
124
+ # Included if the action method exists when `extensions` is called.
125
+ self.autoincludes = {
126
+ create: [:smart_layout, :query_includes],
127
+ destroy: [:smart_layout, :query_includes],
128
+ edit: [:smart_layout, :query_includes],
129
+ index: [:smart_layout, :index_query, :order, :param_filters, :params_to_joins, :query_filter, :query_includes],
130
+ new: [:smart_layout],
131
+ show: [:smart_layout, :query_includes],
132
+ update: [:smart_layout, :query_includes]
133
+ }
134
+
135
+ end
136
+ ```
137
+
138
+ You may want to put your configuration in an initializer like `config/initializers/irie.rb`.
139
+
140
+ ### Controller Configuration
141
+
142
+ The default controller config may be fine, but you can customize it.
143
+
144
+ In the controller, you can set a variety of class attributes with `self.something = ...` in the body of your controller.
145
+
146
+ All of the app-level configuration parameters are configurable in the controller class body, e.g.:
147
+
148
+ ```ruby
149
+ self.can_filter_by_default_using = [:eq]
150
+ self.function_param_names = {}
151
+ self.predicate_prefix = '.'
152
+ self.number_of_records_in_a_page = 15
153
+ self.id_is_primary_key_param = true
154
+ self.update_should_return_entity = false
155
+ ```
156
+
157
+ #### About Extensions
158
+
159
+ As you may have noticed in `autoincludes`, some concerns are included as a package along with the action include.
160
+
161
+ The following assumes that you are using the default autoincludes and included the relevant action.
162
+
163
+ #### Filtering by Attribute(s)
164
+
165
+ Inherited Resources has `has_scope` via the [has_scope][has_scope] dependency, which is still available for use, and is very powerful. But, Irie also has `can_filter_by`. It is an alternative, not a replacement.
166
+
167
+ Unlike `has_scope`, `can_filter_by` doesn't require a `scope` on the model and `has_scope` on the controller. Instead you just have a single `can_filter_by` in the controller rather. Other differences are that the request parameter syntax is more brief, and it adds support for defining deeply associated attributes via either `define_params` or a `through` option.
168
+
169
+ Like the combination of `scope` and `has_scope`, `can_filter_by` filters the index action the request parameter name as a symbol will filter the results by the value of that request parameter, e.g. assuming `:eq` is in the configured `can_filter_by_default_using` in your config, as it is by default:
170
+
171
+ ```ruby
172
+ can_filter_by :title
173
+ ```
174
+
175
+ allows you to:
176
+
177
+ ```
178
+ http://localhost:3000/posts?title=Awesome
179
+ ```
180
+
181
+ or
182
+
183
+ ```
184
+ http://localhost:3000/posts?title.eq=Awesome
185
+ ```
186
+
187
+ Since `.eq` is optional in the param name.
188
+
189
+ And, like `has_scope`, predications are supported. Do `Arel::Predications.public_instance_methods.sort` in Rails console to see the list:
190
+
191
+ ```ruby
192
+ :does_not_match, :does_not_match_all, :does_not_match_any, :eq, :eq_all, :eq_any, :gt,
193
+ :gt_all, :gt_any, :gteq, :gteq_all, :gteq_any, :in, :in_all, :in_any, :lt, :lt_all,
194
+ :lt_any, :lteq, :lteq_all, :lteq_any, :matches, :matches_all, :matches_any, :not_eq,
195
+ :not_eq_all, :not_eq_any, :not_in, :not_in_all, :not_in_any
196
+ ```
197
+
198
+ You can specify these via the `using:` option:
199
+
200
+ ```ruby
201
+ can_filter_by :seen_on, using: [:gteq, :eq_any]
202
+ ```
203
+
204
+ For predicates that take more than one value, by default it expects that you send in multiple request parameters, that way if a value contains something that would be a delimiter of the value, you don't have to worry about additional escaping characters in the value to what you'd have to do otherwise. But, if a value is numeric, for example, you might want to be able to specify a comma-delimited list, and you can do so via:
205
+
206
+ ```ruby
207
+ can_filter_by :mileage, using: [:eq_any], split: ","
208
+ ```
209
+
210
+ Unlike `has_scope` which uses a much lengthier request parameter syntax, by appending the predicate prefix (`.` by default) to the request parameter name, you can use any [ARel][arel] predicate you allowed, e.g.:
211
+
212
+ ```
213
+ http://localhost:3000/posts?seen_on.gteq=2012-08-08
214
+ ```
215
+
216
+ And, `can_filter_by` supports (inner) joins created by `define_params` or if you'd rather, you can specify a `:through` which (inner) joins and sets the deepest symbol in the hash as the key for the parameter value, then does a where, e.g.:
217
+
218
+ ```ruby
219
+ can_filter_by :name, through: {company: {employee: :full_name}}
220
+ ```
221
+
222
+ If a MagicalUnicorn `has_many :friends` and a MagicalUnicorn's friend has a name attribute:
223
+
224
+ ```ruby
225
+ can_filter_by :magical_unicorn_friend_name,
226
+ through: {magical_unicorns:{friends: :name}}
227
+ ```
228
+
229
+ and use this to get valleys associated with unicorns who in turn have a friend named Oscar:
230
+
231
+ ```
232
+ http://localhost:3000/magical_valleys?magical_unicorn_friend_name=Oscar
233
+ ```
234
+
235
+ Similar to specifying a proc/lambda in the `scope` and then using `has_scope` to use it, or defining a `scope` in the model and defining `has_scope` and passing a block into it, you can use `can_filter_by_query`, but again you only have to define something in the controller- not the model and controller. It works a little bit differently; the proc/lambda is in the context of the controller, so unlike the `has_scope` that takes a block, the `controller` doesn't have to be passed in, since that is `self`. The relation object is passed in as `q`, e.g.:
236
+
237
+ ```ruby
238
+ can_filter_by_query a_request_param_name: ->(q, param_value_or_values) {
239
+ q.joins(:some_assoc).where(some_assocs_table_name: {some_attr: param_value_or_values})
240
+ }
241
+ ```
242
+
243
+ The second argument sent to the lambda (`param_value_or_values`) is the request parameter value converted by the `convert_param(param_name, param_values)` method, which may be customized through included extensions or your own extension. See elsewhere in this document for more information about the behavior of this method.
244
+
245
+ The return value of the lambda becomes the new query, so you could really change the behavior of the query depending on the request parameter provided.
246
+
247
+ ##### Customizing Request Parameter Value Conversion
248
+
249
+ Implement the `convert_param(param_name, param_values)` in your controller or an included module, e.g.
250
+
251
+ ```ruby
252
+ # example of custom parameter value converter
253
+ module Example
254
+ module BooleanParams
255
+ extend ::ActiveSupport::Concern
256
+
257
+ TRUE_VALUE = 'true'.freeze
258
+ FALSE_VALUE = 'false'.freeze
259
+
260
+ protected
261
+
262
+ # Converts request param value(s) 'true' to true and 'false' to false
263
+ def convert_param(param_name, param_value_or_values)
264
+ logger.debug("Example::BooleanParams.convert_param(#{param_name.inspect}, #{param_value_or_values.inspect})") if ::Irie.debug?
265
+ param_value_or_values = super if defined?(super)
266
+ if param_value_or_values.is_a? Array
267
+ param_value_or_values.map {|v| convert_boolean(v)}
268
+ else
269
+ convert_boolean(param_value_or_values)
270
+ end
271
+ end
272
+
273
+ private
274
+
275
+ def convert_boolean(value)
276
+ case value
277
+ when TRUE_VALUE
278
+ true
279
+ when FALSE_VALUE
280
+ false
281
+ else
282
+ value
283
+ end
284
+ end
285
+ end
286
+ end
287
+ ```
288
+
289
+ #### Default Filters
290
+
291
+ Like the combination of `scope` and `has_scope` available via [has_scope][has_scope], which you can still use, defaults are supported that are compatible with `can_filter_by`.
292
+
293
+ Specify default filters to define attributes, ARel predicates, and values to use if no filter is provided by the client with the same param name, e.g. if you have:
294
+
295
+ ```ruby
296
+ can_filter_by :attr_name_1
297
+ can_filter_by :production_date, :creation_date, using: [:gt, :eq, :lteq]
298
+ default_filter_by :attr_name_1, eq: 5
299
+ default_filter_by :production_date, :creation_date, gt: 1.year.ago,
300
+ lteq: 1.year.from_now
301
+ ```
302
+
303
+ and both `attr_name_1` and `production_date` are supplied by the client, then it would filter by the client's `attr_name_1` and `production_date` and filter creation_date by both > 1 year ago and <= 1 year from now.
304
+
305
+ #### Extensions
306
+
307
+ ##### Count
308
+
309
+ In the controller:
310
+
311
+ ```ruby
312
+ extensions :count
313
+ ```
314
+
315
+ enables:
316
+
317
+ ```
318
+ http://localhost:3000/posts?count=
319
+ ```
320
+
321
+ That will set the `@count` instance variable that you can use in your view.
322
+
323
+ Use `extensions :autorender_count` to render count automatically for non-HTML (JSON, etc.) views.
324
+
325
+ ##### Page Count
326
+
327
+ In the controller:
328
+
329
+ ```ruby
330
+ extensions :paging
331
+ ```
332
+
333
+ enables:
334
+
335
+ ```
336
+ http://localhost:3000/posts?page_count=
337
+ ```
338
+
339
+ That will set the `@page_count` instance variable that you can use in your view.
340
+
341
+ Use `extensions :autorender_page_count` to render count automatically for non-HTML (JSON, etc.) views.
342
+
343
+ ##### Getting a Page
344
+
345
+ In the controller:
346
+
347
+ ```ruby
348
+ extensions :paging
349
+ ```
350
+
351
+ To access each page of results:
352
+
353
+ ```
354
+ http://localhost:3000/posts?page=1
355
+ http://localhost:3000/posts?page=2
356
+ ```
357
+
358
+ To set page size at application level:
359
+
360
+ ```ruby
361
+ ::Irie.number_of_records_in_a_page = 15
362
+ ```
363
+
364
+ To set page size at controller level:
365
+
366
+ ```ruby
367
+ self.number_of_records_in_a_page = 15
368
+ ```
369
+
370
+ ##### Offset and Limit
371
+
372
+ In the controller:
373
+
374
+ ```ruby
375
+ extensionss :offset, :limit
376
+ ```
377
+
378
+ enables:
379
+
380
+ ```
381
+ http://localhost:3000/posts?offset=5
382
+ http://localhost:3000/posts?limit=5
383
+ ```
384
+
385
+ You can combine them to act like page:
386
+
387
+ ```
388
+ http://localhost:3000/posts?limit=15
389
+ http://localhost:3000/posts?offset=15&limit=15
390
+ http://localhost:3000/posts?offset=30&limit=15
391
+ ```
392
+
393
+ #### Order
394
+
395
+ You can allow request specified order:
396
+
397
+ ```ruby
398
+ can_order_by :foo_date, :foo_color
399
+ ```
400
+
401
+ Will let the client send the order parameter with those parameters and optional +/- prefix to designate sort direction, e.g. the following will sort by foo_date ascending then foo_color descending:
402
+
403
+ ```
404
+ http://localhost:3000/posts?order=foo_date,-foo_color
405
+ ```
406
+
407
+ The `default_order_by` specifies an ordered array of ascending attributes and/or hashes of attributes to sort direction:
408
+
409
+ ```ruby
410
+ default_order_by :posted_at => :desc, :id => :desc
411
+ ```
412
+
413
+ or:
414
+
415
+ ```ruby
416
+ default_order_by {:this_is_desc => :desc}, :this_is_asc,
417
+ {:no_different_than_a_symbol => :asc},
418
+ :this_is_asc_also, :id => :desc
419
+ ```
420
+
421
+ `can_order_by` and `default_order_by` support joins/`names_params` as well as a `through` option on `can_order_by` similar to `can_filter_by`.
422
+
423
+ #### Custom Index Queries
424
+
425
+ To filter the list where the status_code attribute is 'green':
426
+
427
+ ```ruby
428
+ index_query ->(q) { q.where(:status_code => 'green') }
429
+ ```
430
+
431
+ You can also filter out items that have associations that don't have a certain attribute value (or anything else you can think up with [ARel][arel]/[ActiveRecord relations][ar]), e.g. to filter the list where the object's apples and pears associations are green:
432
+
433
+ ```ruby
434
+ index_query ->(q) {
435
+ q.joins(:apples, :pears)
436
+ .where(apples: {color: 'green'})
437
+ .where(pears: {color: 'green'})
438
+ }
439
+ ```
440
+
441
+ To avoid n+1 queries, use `.includes(...)` in your query to eager load any associations that you will need in the JSON view.
442
+
443
+ #### Smart Layout
444
+
445
+ By default, Rails rendering goes through some extra hoops to attempt to find your layout unless you tell it not to, so With default autoincludes, Irie will use the `:smart_layout` extension to specify `layout: false` unless the request format is html.
446
+
447
+ #### Avoid n+1 Queries
448
+
449
+ ```ruby
450
+ # load all the posts and the associated category and comments for each post
451
+ query_includes :category, :comments
452
+ ```
453
+
454
+ or
455
+
456
+ ```ruby
457
+ # load all of the associated posts, the associated posts’ tags and comments, and every comment’s guest association
458
+ query_includes posts: [{comments: :guest}, :tags]
459
+ ```
460
+
461
+ and action-specific:
462
+
463
+ ```ruby
464
+ query_includes_for :create, are: [:category, :comments]
465
+ query_includes_for :index, :show, are: [posts: [{comments: :guest}, :tags]]
466
+ ```
467
+
468
+ #### Using define_params vs :through option
469
+
470
+ The `:through` option in `can_filter_by` and `can_order_by` just uses `define_params` to set the attribute name alias and options (which is parsed into a joins hash and attribute name internally). So, if you don't mind a little more typing, it might make the intent clearer, e.g.
471
+
472
+ ```ruby
473
+ define_params name: {company: {employee: :full_name}},
474
+ color: :external_color
475
+ can_filter_by :name
476
+ default_filter_by :name, eq: 'Guest'
477
+ can_order_by :color
478
+ default_filter_by :color, eq: 'blue'
479
+ ```
480
+
481
+ #### Other Extensions
482
+
483
+ The following concerns, which you can include via `extensions ...` or via including the corresponding module, might also be of use in your controller:
484
+
485
+ * `:nil_params` - convert 'NULL', 'null', and 'nil' to nil when passed in as request params.
486
+
487
+ #### Writing Your Own Extensions
488
+
489
+ Extensions are just modules. There is no magic.
490
+
491
+ The somewhat special thing about Irie extensions if that you can `@action_result = ...; throw(:action_break)` in any method that is called by an Irie action and it will break the execution of the action and return `@action_result`. This allows the ease of control that you'd have typically in a single long action method, but lets you use modules to easily share action method functionality. To those unfamiliar, `throw` in Ruby is a normal flow control mechanism, unlike `raise` which is for exceptions.
492
+
493
+ Some hopefully good examples of how to extend modules are in lib/irie/extensions/* and the actions themselves are in lib/irie/actions/*. Get familiar with the code even if you don't plan on customizing, if for no other reason than to have another set of eyes on the code.
494
+
495
+ Here's another example:
496
+
497
+ ```ruby
498
+ # Converts all 'true' and 'false' param values to true and false
499
+ module BooleanParams
500
+ extend ::ActiveSupport::Concern
501
+
502
+ protected
503
+
504
+ def convert_param(param_name, param_values)
505
+ case param_values
506
+ when 'true'
507
+ true
508
+ when 'false'
509
+ false
510
+ else
511
+ super if defined?(super)
512
+ end
513
+ end
514
+
515
+ end
516
+ ```
517
+
518
+ If you are just doing regular `include`'s in your controllers, that's all you need. If you'd like to use `extensions`, you get autoincludes and can use symbols, e.g. in `app/controllers/concerns/service_controller.rb`:
519
+
520
+ ```ruby
521
+ module ServiceController
522
+ extend ::ActiveSupport::Concern
523
+
524
+ included do
525
+ inherit_resources
526
+ respond_to :json
527
+
528
+ # reference as string so we don't load the concern before it is used.
529
+ ::Irie.register_extension :boolean_params, '::Example::BooleanParams'
530
+
531
+ # register_extension also can define the order of inclusion, e.g.:
532
+ # ::Irie.register_extension :boolean_params, '::Example::BooleanParams', include: :last #default
533
+ # ::Irie.register_extension :boolean_params, '::Example::BooleanParams', include: :first
534
+ # ::Irie.register_extension :boolean_params, '::Example::BooleanParams', after: :nil_params
535
+ # ::Irie.register_extension :boolean_params, '::Example::BooleanParams', before: :nil_params
536
+
537
+ end
538
+
539
+ end
540
+ ```
541
+
542
+ Now you could use this in your controller:
543
+
544
+ ```ruby
545
+ include ServiceController
546
+
547
+ actions :index
548
+ extensions :boolean_params
549
+ ```
550
+
551
+ Doing that doesn't make as much sense when you just have modules in the root namespace, but it might if you have longer namespaces for organization and to avoid class/module name conflicts.
552
+
553
+ #### Primary Keys
554
+
555
+ Supports composite primary keys. If `resource_class.primary_key.is_a?(Array)`, show/edit/update/destroy will use your two or more request params for the ids that make up the composite.
556
+
557
+ #### Exception Handling
558
+
559
+ Rails 4 has basic exception handling in the [public_exceptions][public_exceptions] and [show_exceptions][show_exceptions] Rack middleware.
560
+
561
+ If you want to customize Rails 4's Rack exception handling, search the web for customizing `config.exceptions_app`, although the default behavior should work for most.
562
+
563
+ You can also use `rescue_from` or `around_action` in Rails to have more control over error rendering.
564
+
565
+ ### Troubleshooting
566
+
567
+ #### Irie::Extensions::QueryIncludes
568
+
569
+ If you get `missing FROM-clause entry for table` errors, it might mean that `query_includes`/`query_includes_for` you are using are overlapping with joins that are being done in the query. This is the nasty head of AR relational includes, unfortunately.
570
+
571
+ To fix, you may decide to either: (1) change order/definition of includes in `query_includes`/`query_includes_for`, (2) don't use `query_includes`/`query_includes_for` for the actions it affects (may cause n+1 queries), (3) implement `apply_includes` to do includes in an appropriate order (messy), or (4) use custom query (if index/custom list action) to define joins with handcoded SQL, e.g. (thanks to Tommy):
572
+
573
+ ```ruby
574
+ index_query ->(q) {
575
+ # Using standard joins performs an INNER JOIN like we want, but doesn't
576
+ # eager load.
577
+ # Using includes does an eager load, but does a LEFT OUTER JOIN, which
578
+ # isn't really what we want, but in this scenario is probably ok.
579
+ # Using standard joins & includes results in bad SQL with table aliases.
580
+ # So, using includes & custom joins seems like a decent solution.
581
+ q.includes(:bartender, :waitress, :owner, :customer)
582
+ .joins('INNER JOIN employees bartenders ON bartenders.employee_id = ' +
583
+ 'shifts.bartender_id')
584
+ .joins('INNER JOIN waitresses shift_workers ON shift_workers.id = ' +
585
+ 'shifts.waitress_id')
586
+ .where(bartenders: {certified: 'yes'})
587
+ .where(shift_workers: {attitude: 'great'})
588
+ }
589
+
590
+ # set includes for all actions except index
591
+ query_includes :owner, :customer, :bartender, :waitress
592
+
593
+ # includes specified in index query
594
+ query_includes_for :index, are: []
595
+ ```
596
+
597
+ #### Debugging Includes
598
+
599
+ ##### Logging
600
+
601
+ If you enabled Irie's debug option via:
602
+
603
+ ```ruby
604
+ ::Irie.debug = true
605
+ ```
606
+
607
+ Then all the included modules (actions, extensions) will use `logger.debug ...` to log some information about what is executed.
608
+
609
+ To log debug to console only in your tests, you could put this in your test helper:
610
+
611
+ ```ruby
612
+ ::Irie.debug = true
613
+ ::ActionController::Base.logger = Logger.new(STDOUT)
614
+ ::ActionController::Base.logger.level = Logger::DEBUG
615
+ ```
616
+
617
+ However, that might not catch all the initialization debug logging that could occur. Instead, you might put the following into the block in `config/environments/test.rb`:
618
+
619
+ ```ruby
620
+ ::Irie.debug = true
621
+ config.log_level = :debug
622
+ ```
623
+
624
+ ### restful_json
625
+
626
+ The project was originally named [restful_json][restful_json]. Old commit tags corresponding to restful_json versions may be found in [legacy][legacy].
627
+
628
+ ### Release Notes
629
+
630
+ See [changelog][changelog] and git log.
631
+
632
+ ### Contributing
633
+
634
+ Please fork, make changes in a separate branch, and do a pull request. Thanks!
635
+
636
+ ### Authors
637
+
638
+ This was written by [FineLine Prototyping, Inc.](http://www.finelineprototyping.com) by the following contributors:
639
+ * [Gary Weaver](https://github.com/garysweaver)
640
+ * [Tommy Odom](https://github.com/tpodom)
641
+
642
+ ### License
643
+
644
+ Copyright (c) 2013 FineLine Prototyping, Inc., released under the [MIT license][lic].
645
+
646
+ [travis]: http://travis-ci.org/FineLinePrototyping/irie
647
+ [badgefury]: http://badge.fury.io/rb/irie
648
+ [arel]: https://github.com/rails/arel
649
+ [ar]: http://api.rubyonrails.org/classes/ActiveRecord/Relation.html
650
+ [has_scope]: https://github.com/plataformatec/has_scope
651
+ [public_exceptions]: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/public_exceptions.rb
652
+ [show_exceptions]: https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
653
+ [changelog]: https://github.com/FineLinePrototyping/irie/blob/master/CHANGELOG.md
654
+ [inherited_resources]: https://github.com/josevalim/inherited_resources
655
+ [restful_json]: http://rubygems.org/gems/restful_json
656
+ [legacy]: http://github.com/FineLinePrototyping/irie/blob/master/LEGACY.md
657
+ [lic]: http://github.com/FineLinePrototyping/irie/blob/master/LICENSE