hobo 2.0.1 → 2.1.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES-2.1.markdown +57 -0
  3. data/Gemfile +1 -1
  4. data/VERSION +1 -1
  5. data/app/helpers/hobo_permissions_helper.rb +1 -1
  6. data/app/helpers/hobo_route_helper.rb +10 -79
  7. data/config/routes.rb +2 -2
  8. data/hobo.gemspec +1 -1
  9. data/lib/generators/hobo/admin_subsite/admin_subsite_generator.rb +3 -1
  10. data/lib/generators/hobo/controller.rb +4 -1
  11. data/lib/generators/hobo/front_controller/front_controller_generator.rb +7 -6
  12. data/lib/generators/hobo/i18n/templates/hobo.en.yml +2 -1
  13. data/lib/generators/hobo/i18n/templates/hobo.es.yml +1 -0
  14. data/lib/generators/hobo/i18n/templates/hobo.ru.yml +1 -0
  15. data/lib/generators/hobo/routes/router.rb +5 -3
  16. data/lib/generators/hobo/routes/templates/hobo_routes.rb.erb +0 -36
  17. data/lib/generators/hobo/setup_wizard/setup_wizard_generator.rb +2 -2
  18. data/lib/hobo.rb +2 -2
  19. data/lib/hobo/controller.rb +1 -1
  20. data/lib/hobo/controller/model.rb +4 -4
  21. data/lib/hobo/extensions/active_record/associations/association.rb +1 -1
  22. data/lib/hobo/extensions/active_record/associations/scope.rb +6 -5
  23. data/lib/hobo/extensions/active_record/relation_with_origin.rb +9 -7
  24. data/lib/hobo/model.rb +1 -2
  25. data/lib/hobo/model/accessible_associations.rb +4 -5
  26. data/lib/hobo/model/permissions.rb +7 -6
  27. data/lib/hobo/model/scopes.rb +1 -3
  28. data/lib/hobo/model/scopes/apply_scopes.rb +3 -3
  29. data/test/irt/generators/admin_subsite.irt +6 -0
  30. metadata +17 -39
  31. data/test/doctest/hobo/multi_model_forms.rdoctest +0 -260
  32. data/test/doctest/hobo/scopes.rdoctest +0 -375
@@ -1,375 +0,0 @@
1
- Hobo Scopes
2
- {: .document-title}
3
-
4
- doctest: prepare testapp environment
5
- doctest_require: '../prepare_testapp'
6
- {.hidden}
7
-
8
- Hobo scopes are an extension of the *named scope* and *dynamic finder*
9
- functionality introduced in Rails 2.1, 2.2 and 2.3.
10
-
11
- Most of these scopes work by calling `named_scope` the first time they
12
- are invoked. They should work at the same speed as a named scope on
13
- subsequent invocations.
14
-
15
- However, this does substantially slow down `method_missing` on your
16
- model's class. If `ActiveRecord::Base.method_missing` is used often,
17
- you may wish to disable this module. (FIXME: how to do that)
18
-
19
- Contents
20
- {: .contents-heading}
21
-
22
- - contents
23
- {:toc}
24
-
25
- This document was created using the tool
26
- [rubydoctest](http://github.com/tablatom/rubydoctest). This means
27
- that this file serves as both documentation and test. As a side
28
- effect, it also ensures that errors do not creep into the sample code
29
- in this documentation.
30
- {.hidden}
31
-
32
- The idea behind rubydoctest is that you should be able to recreate
33
- everything in this document from an irb console. It is recommended
34
- that you skip down to the [fixture definitions](#fixture_definition).
35
- Nobody but the computer needs to read the rest of this section.
36
- {.hidden}
37
-
38
- Let's set up a few models for our testing:
39
-
40
- >> File.open("#{Rails.root}/app/models/person.rb", "w") do |f|
41
- f.write("""
42
- class Person < ActiveRecord::Base
43
- hobo_model
44
-
45
- fields do
46
- name :string
47
- born_at :date
48
- code :integer
49
- male :boolean
50
- timestamps
51
- end
52
- attr_accessible :name, :born_at, :code, :male
53
-
54
- lifecycle(:key_timestamp_field => false) do
55
- state :inactive, :active
56
- end
57
-
58
- has_many :friendships
59
- has_many :friends, :through => :friendships
60
- end
61
- """)
62
- end
63
- >> File.open("#{Rails.root}/app/models/friendship.rb", "w") do |f|
64
- f.write("""
65
- class Friendship < ActiveRecord::Base
66
- hobo_model
67
- fields
68
- attr_accessible :person, :friend
69
- belongs_to :person
70
- belongs_to :friend, :class_name => 'Person'
71
- end
72
- """)
73
- end
74
-
75
- Generate a migration and run it:
76
- {.hidden}
77
-
78
- >> system("rails g hobo:migration -m -n")
79
- >> ActionDispatch::Reloader.cleanup!
80
- >> ActionDispatch::Reloader.prepare!
81
- >> Person.connection.clear_cache!
82
- >> Person.connection.schema_cache.clear!
83
- >> Person.reset_column_information
84
- >> Person.columns.*.name
85
- => ["id", "name", "born_at", "code", "male", "created_at", "updated_at", "state"]
86
- {.hidden}
87
-
88
- And create a couple of fixtures:
89
-
90
- >>
91
- Bryan = Person.new(:name => "Bryan", :code => 17,
92
- :born_at => Date.new(1973,4,8), :male => true)
93
- >> Bryan.state = "active"
94
- >> Bryan.save!
95
- >>
96
- Bethany = Person.new(:name => "Bethany", :code => 42,
97
- :born_at => Date.new(1975,5,13), :male => false)
98
- >> Bethany.state = "inactive"
99
- >> Bethany.save!
100
- >> Friendship.new(:person => Bryan, :friend => Bethany).save!
101
-
102
- Hack the `created_at` column to get predictable sorting.
103
-
104
- >> Bethany.created_at = Date.new(2000)
105
- >> Bethany.save!
106
-
107
- We're ready to get going.
108
-
109
- # Simple Scopes
110
-
111
- ## \_is
112
-
113
- Most Hobo scopes work by appending an appropriate query string to the
114
- field name. In this case, the hobo scope function name is the name of
115
- your database column, followed by `_is`. It returns an Array of models.
116
-
117
- It works the same as a dynamic finder:
118
-
119
- >> Person.find_all_by_name("Bryan").*.name
120
- => ["Bryan"]
121
- >> Person.name_is("Bryan").*.name
122
- => ["Bryan"]
123
- >> Person.code_is(17).*.name
124
- => ["Bryan"]
125
- >> Person.code_is(99).length
126
- => 0
127
-
128
- ## \_is\_not
129
-
130
- But the Hobo scope form allows us to supply several variations
131
-
132
- >> Person.name_is_not("Bryan").*.name
133
- => ["Bethany"]
134
-
135
- ## \_contains
136
-
137
- Case insensitive.
138
-
139
- >> Person.name_contains("y").*.name
140
- => ["Bryan", "Bethany"]
141
-
142
- ## \_does\_not\_contain
143
-
144
- Case insensitive.
145
-
146
- >> Person.name_does_not_contain("b").*.name
147
- => []
148
-
149
- ## \_starts
150
-
151
- Case insensitive.
152
-
153
- >> Person.name_starts("b").*.name
154
- => ["Bryan", "Bethany"]
155
-
156
- ## \_does\_not\_start
157
-
158
- Case insensitive.
159
-
160
- >> Person.name_does_not_start("B").length
161
- => 0
162
-
163
- ## \_ends
164
-
165
- >> Person.name_ends("y").*.name
166
- => ["Bethany"]
167
-
168
- ## \_does\_not\_end
169
-
170
- >> Person.name_does_not_end("y").*.name
171
- => ["Bryan"]
172
-
173
- # Boolean scopes
174
-
175
- ## \_
176
-
177
- If you use the name of the column by itself, the column is of type
178
- boolean, and no function is already defined on the model class with
179
- the name, Hobo scopes adds a dynamic finder to return all records with
180
- the boolean column set to `true`
181
-
182
- >> Person.male.*.name
183
- => ["Bryan"]
184
-
185
- ## not\_
186
-
187
- You can also search for boolean records that are not `true`. This
188
- includes all records that are set to `false` or `NULL`.
189
-
190
- >> Person.not_male.*.name
191
- => ["Bethany"]
192
-
193
- # Date scopes
194
-
195
- Date scopes work only with columns that have a name ending in "_at".
196
- The "_at" is omitted when using these finders.
197
-
198
- ## \_before
199
-
200
- >> Person.born_before(Date.new(1974)).*.name
201
- => ["Bryan"]
202
-
203
- ## \_after
204
-
205
- >> Person.born_after(Date.new(1974)).*.name
206
- => ["Bethany"]
207
-
208
- ## \_between
209
-
210
- >> Person.born_between(Date.new(1974), Date.today).*.name
211
- => ["Bethany"]
212
-
213
- # Lifecycle scopes
214
-
215
- If you have a [lifecycle](/manual/lifecycles) defined, each state name
216
- can be used as a dynamic finder.
217
-
218
- >> Person.active.*.name
219
- => ["Bryan"]
220
-
221
- # Key scopes
222
-
223
- This isn't very useful:
224
-
225
- >> Person.is(Bryan).*.name
226
- => ["Bryan"]
227
-
228
- But this is:
229
-
230
- >> Person.is_not(Bryan).*.name
231
- => ["Bethany"]
232
-
233
- # Static scopes
234
-
235
- These scopes do not contain the column name.
236
-
237
- ## by\_most\_recent
238
-
239
- Sorting on the `created_at` column:
240
-
241
- >> Person.by_most_recent.*.name
242
- => ["Bryan", "Bethany"]
243
-
244
- ## recent
245
-
246
- Gives the N most recent items:
247
-
248
- >> Person.recent(1).*.name
249
- => ["Bryan"]
250
-
251
- ## limit
252
-
253
- >> Person.limit(1).*.name
254
- => ["Bryan"]
255
-
256
- ## order\_by
257
-
258
- >> Person.order_by(:code).*.name
259
- => ["Bryan", "Bethany"]
260
-
261
- ## include
262
-
263
- DEPRECATED: Automatic scope :include has been deprecated: use :includes instead.
264
-
265
- ## includes
266
-
267
- >> Person.search("B", :name).includes(:friends).*.name # test LH#839
268
- => ["Bryan", "Bethany"]
269
-
270
- >> Person.includes(:friends).*.name
271
- => ["Bryan", "Bethany"]
272
-
273
- ## search
274
-
275
- Search for text in the specified column(s).
276
-
277
- >> Person.search("B", :name).*.name
278
- => ["Bryan", "Bethany"]
279
-
280
- # Association Scopes
281
-
282
- ## with\_
283
-
284
- Find the records that contain the specified record in an association
285
-
286
- >> Person.with_friendship(Friendship.first).*.name
287
- => ["Bryan"]
288
- >> Person.with_friend(Bethany).*.name
289
- => ["Bryan"]
290
-
291
- You can also specify multiple records with the plural form
292
-
293
- >> Person.with_friends(Bethany, nil).*.name
294
- => ["Bryan"]
295
-
296
- ## any\_of\_
297
-
298
- This works on plural associations to find a model associated with any of the arguments
299
-
300
- >> Person.any_of_friends(Bethany, Bryan).*.name
301
- => ["Bryan"]
302
-
303
- ## without\_
304
-
305
- >> Person.without_friend(Bethany).*.name
306
- => ["Bethany"]
307
- >> Person.without_friends(Bethany, nil).*.name
308
- => ["Bethany"]
309
-
310
-
311
- ## \_is
312
-
313
- You can use \_is on a `:has_one` or a `:belongs_to` relationship:
314
-
315
- >> Friendship.person_is(Bryan).*.friend.*.name
316
- => ["Bethany"]
317
-
318
- ## \_is\_not
319
-
320
- >> Friendship.person_is_not(Bryan)
321
- => []
322
-
323
- # Scoping Associations
324
-
325
- When defining an association, you can add a scope:
326
-
327
- >>
328
- class Person
329
- has_many :active_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => :active
330
- has_many :inactive_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => :inactive
331
- end
332
-
333
- >> Bryan.inactive_friends.*.name
334
- => ["Bethany"]
335
- >> Bryan.active_friends.*.name
336
- => []
337
-
338
- or several scopes:
339
-
340
- >>
341
- class Person
342
- has_many :inactive_female_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => [:inactive, :not_male]
343
- has_many :active_female_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => [:active, :not_male]
344
- has_many :inactive_male_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => [:inactive, :male]
345
- end
346
-
347
- >> Bryan.inactive_female_friends.*.name
348
- => ["Bethany"]
349
- >> Bryan.active_female_friends.*.name
350
- => []
351
- >> Bryan.inactive_male_friends.*.name
352
- => []
353
-
354
- You can parameterize the scopes:
355
-
356
- >>
357
- class Person
358
- has_many :y_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => { :name_contains => 'y' }
359
- has_many :z_friends, :class_name => "Person", :through => :friendships, :source => :friend, :scope => { :name_contains => 'z' }
360
- end
361
-
362
- >> Bryan.y_friends.*.name
363
- => ["Bethany"]
364
- >> Bryan.z_friends.*.name
365
- => []
366
-
367
-
368
- # Chaining
369
-
370
- Like named scopes, Hobo scopes can be chained:
371
-
372
- >> Bryan.inactive_friends.inactive.*.name
373
- => ["Bethany"]
374
-
375
- {.hidden}