hobo 0.8.5 → 0.8.6

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.
Files changed (68) hide show
  1. data/CHANGES.txt +41 -0
  2. data/Manifest +1 -5
  3. data/Rakefile +10 -3
  4. data/bin/hobo +38 -15
  5. data/dryml_generators/rapid/cards.dryml.erb +7 -7
  6. data/dryml_generators/rapid/pages.dryml.erb +52 -24
  7. data/hobo.gemspec +42 -322
  8. data/init.rb +0 -7
  9. data/lib/active_record/association_collection.rb +9 -0
  10. data/lib/hobo.rb +13 -14
  11. data/lib/hobo/accessible_associations.rb +32 -7
  12. data/lib/hobo/authentication_support.rb +1 -1
  13. data/lib/hobo/controller.rb +5 -7
  14. data/lib/hobo/dryml.rb +9 -2
  15. data/lib/hobo/dryml/dryml_builder.rb +11 -12
  16. data/lib/hobo/dryml/dryml_doc.rb +22 -24
  17. data/lib/hobo/dryml/dryml_generator.rb +41 -4
  18. data/lib/hobo/dryml/part_context.rb +5 -3
  19. data/lib/hobo/dryml/template.rb +7 -7
  20. data/lib/hobo/dryml/template_environment.rb +11 -22
  21. data/lib/hobo/dryml/template_handler.rb +94 -25
  22. data/lib/hobo/find_for.rb +2 -2
  23. data/lib/hobo/hobo_helper.rb +21 -21
  24. data/lib/hobo/include_in_save.rb +9 -5
  25. data/lib/hobo/lifecycles/transition.rb +2 -2
  26. data/lib/hobo/model.rb +11 -61
  27. data/lib/hobo/model_controller.rb +28 -29
  28. data/lib/hobo/model_router.rb +12 -13
  29. data/lib/hobo/permissions.rb +47 -37
  30. data/lib/hobo/permissions/associations.rb +1 -1
  31. data/lib/hobo/scopes/association_proxy_extensions.rb +5 -6
  32. data/lib/hobo/scopes/automatic_scopes.rb +7 -4
  33. data/lib/hobo/tasks/rails.rb +4 -0
  34. data/lib/hobo/user.rb +0 -1
  35. data/lib/hobo/user_controller.rb +3 -1
  36. data/lib/hobo/view_hints.rb +17 -3
  37. data/rails_generators/hobo/hobo_generator.rb +1 -0
  38. data/rails_generators/hobo_front_controller/templates/functional_test.rb +1 -11
  39. data/rails_generators/hobo_front_controller/templates/index.dryml +1 -6
  40. data/rails_generators/hobo_rapid/hobo_rapid_generator.rb +1 -0
  41. data/rails_generators/hobo_rapid/templates/hobo-rapid.css +3 -2
  42. data/rails_generators/hobo_rapid/templates/hobo-rapid.js +24 -15
  43. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/clean.css +17 -12
  44. data/rails_generators/hobo_rapid/templates/themes/clean/public/stylesheets/rapid-ui.css +6 -2
  45. data/rails_generators/hobo_rapid/templates/themes/clean/views/clean.dryml +2 -2
  46. data/rails_generators/hobo_user_model/templates/forgot_password.erb +2 -2
  47. data/rails_generators/hobo_user_model/templates/model.rb +2 -2
  48. data/taglibs/rapid.dryml +3 -2
  49. data/taglibs/rapid_core.dryml +21 -16
  50. data/taglibs/rapid_document_tags.dryml +1 -1
  51. data/taglibs/rapid_editing.dryml +7 -10
  52. data/taglibs/rapid_forms.dryml +115 -26
  53. data/taglibs/rapid_generics.dryml +13 -3
  54. data/taglibs/rapid_lifecycles.dryml +18 -1
  55. data/taglibs/rapid_navigation.dryml +50 -61
  56. data/taglibs/rapid_pages.dryml +103 -19
  57. data/taglibs/rapid_plus.dryml +54 -6
  58. data/taglibs/rapid_support.dryml +38 -1
  59. data/taglibs/rapid_user_pages.dryml +17 -5
  60. data/test/permissions/models/models.rb +24 -12
  61. data/test/permissions/models/test.sqlite3 +0 -0
  62. metadata +6 -15
  63. data/lib/extensions/test_case.rb +0 -129
  64. data/lib/hobo/composite_model.rb +0 -73
  65. data/lib/hobo/model_support.rb +0 -44
  66. data/tasks/fix_dryml.rake +0 -143
  67. data/tasks/generate_tag_reference.rake +0 -192
  68. data/test/dryml/complilation_test.rb +0 -261
@@ -1,3 +1,24 @@
1
+ <!-- Rapid Support is the home for some tags that are useful in defining other tags. -->
2
+
3
+
4
+ <!-- Call with the context set to a record. Repeats the content of the tag with `this` and `this_field` set to the value and name of each of the record's fields in turn. E.g. this is useful for generating a form containing each of the fields. Tags like `<field-list>` and `<table>` forward their attributes to this tag and also have the features described here. For example, the `fields` attribute to `<field-list>` supports the same options as described here.
5
+
6
+ This tag is in need of a review - it's a bit funky.
7
+
8
+ ### Attributes
9
+
10
+ - `fields` - set to one of:
11
+ - A model class - equivalent to listing all of the regular 'content columns' of that model
12
+ - '`*`' - equivalent to listing all of the regular 'content columns' of the current record
13
+ - A comma separated list of field names.
14
+ Defaults to '`*`'
15
+ - `assocaitions` - set to `has_many` to select the associations `has_many` relationships used as the "fields". Do not also give the `fields` attribute.
16
+ - `skip` - comma separated list of field names to omit.
17
+ - `skip-associations` - set to `has-many` to omit all `has_many` associations.
18
+ - `include-timestamps` - whether or not to include the standard ActiveRecord timestamp fields such as `created_at` and `updated_at`. Defaults to false.
19
+ - `force-all` - by default fields are skipped if the current user does not have view permission. Set `force-all` to true to skip this permission check and include all the fields.
20
+
21
+ -->
1
22
  <def tag="with-fields" attrs="fields, associations, skip, skip-associations, include-timestamps, force-all"><%
2
23
  fields.nil? || associations.nil? or raise ArgumentError, "with-fields -- specify either fields or associations but not both"
3
24
 
@@ -31,6 +52,22 @@
31
52
  end
32
53
  %></def>
33
54
 
55
+ <!-- Call with the context set to a model class. Repeats the content of the tag with `this` set name of each of the model's fields in turn. E.g. this tag is used when generating the heading row in a `<table fields='...'/>`.
56
+
57
+ This tag is in need of a review - it's a bit funky.
58
+
59
+ ### Attributes
60
+
61
+ - `fields` - set to one of:
62
+ - A model class - equivalent to listing all of the regular 'content columns' of that model
63
+ - '`*`' - equivalent to listing all of the regular 'content columns' of the current record
64
+ - A comma separated list of field names.
65
+ Defaults to '`*`'
66
+ - `skip` - comma separated list of field names to omit.
67
+ - `skip-associations` - set to `has-many` to omit all `has_many` associations.
68
+ - `include-timestamps` - whether or not to include the standard ActiveRecord timestamp fields such as `created_at` and `updated_at`. Defaults to false.
69
+
70
+ -->
34
71
  <def tag="with-field-names" attrs="fields, skip, skip-associations, include-timestamps"><%=
35
72
  field_names = if fields.nil? || fields == "*" || fields.is_a?(Class)
36
73
  klass = fields.is_a?(Class) ? fields : this.member_class
@@ -53,7 +90,7 @@
53
90
  field_names -= comma_split(skip) if skip
54
91
  scope.new_scope :field_name => nil, :field_path => nil do
55
92
  field_names.map do |n|
56
- scope.field_name = n == "this" ? this.member_class.name : n.to_s.gsub("." , "_")
93
+ scope.field_name = n == "this" ? this.member_class.try.name : n.to_s.gsub("." , "_")
57
94
  scope.field_path = n
58
95
  parameters.default
59
96
  end
@@ -1,11 +1,15 @@
1
+ <!-- Rapid User Pages contains tags that implement the basics of Hobo's user management: log in, sign up, forgot password etc. -->
2
+
3
+ <!-- Some of the user pages use a simplified layout that does not feature things like the main nav and live-search. This tag defines that page -->
1
4
  <def tag="simple-page">
2
5
  <page without-live-search without-main-nav merge>
3
- <account-nav: replace><dev-user-changer/></account-nav:>
6
+ <account-nav: replace />
4
7
  </page>
5
8
  </def>
6
9
 
7
10
 
8
- <def tag="login-page" attrs="remember-me">
11
+ <!-- Simple log-in page -->
12
+ <def tag="login-page">
9
13
  <% remember_me = true if remember_me.nil? %>
10
14
  <simple-page title="Log in" merge>
11
15
 
@@ -31,9 +35,11 @@
31
35
  </item-value>
32
36
  </labelled-item>
33
37
 
34
- <labelled-item if="&remember_me">
38
+ <labelled-item param="remember-me">
35
39
  <item-label class="field-label" param="remember-me-label">Remember me:</item-label>
36
- <item-value><input type="checkbox" name="remember_me" id="remember-me" param="remember-me-input"/></item-value>
40
+ <item-value>
41
+ <input type="checkbox" name="remember_me" id="remember-me" param="remember-me-input" checked/>
42
+ </item-value>
37
43
  </labelled-item>
38
44
  </labelled-item-list>
39
45
  <div param="actions">
@@ -48,6 +54,8 @@
48
54
  </def>
49
55
 
50
56
 
57
+ <!-- The page that initiates the forgotten password process. Contians a single text-input where the user can provide
58
+ their email address -->
51
59
  <def tag="forgot-password-page">
52
60
  <simple-page title="Forgotten Password" merge>
53
61
 
@@ -81,7 +89,9 @@
81
89
  </simple-page>
82
90
  </def>
83
91
 
84
-
92
+ <!-- Second page in the forgotten password process. Informs the user that the email has been sent "If the e-mail address you
93
+ entered is in our records". This is to avoid a privacy concern that the forgotten-password mechanism can be otherwise used to tell
94
+ if a given email is associated with an account or not. -->
85
95
  <def tag="forgot-password-email-sent-page">
86
96
  <simple-page>
87
97
  <body: class="forgot-password-page" param/>
@@ -105,6 +115,7 @@
105
115
  </def>
106
116
 
107
117
 
118
+ <!-- The page that is displayed on attempting to log in to an account that has been disabled. -->
108
119
  <def tag="account-disabled-page">
109
120
 
110
121
  <simple-page title="Account not available" merge>
@@ -125,6 +136,7 @@
125
136
  </def>
126
137
 
127
138
 
139
+ <!-- Basic account page that provides the ability for the user to change their email address and password. -->
128
140
  <def tag="account-page">
129
141
 
130
142
  <page title="#{name} - Account" merge>
@@ -6,11 +6,6 @@ $:.unshift "#{HOBO_HOME}/hobo/lib"
6
6
  require 'rubygems'
7
7
  require 'sqlite3'
8
8
  require 'activerecord'
9
- require 'hobosupport'
10
- require 'hobofields'
11
- require 'hobo'
12
-
13
- Hobo::Model.enable
14
9
 
15
10
  module Models
16
11
 
@@ -19,27 +14,27 @@ module Models
19
14
  HOME = File.dirname(__FILE__)
20
15
 
21
16
  def model(name, &b)
22
- klass = Object.const_set(name, Class.new(ActiveRecord::Base))
17
+ klass = Object.const_get(name)
23
18
  klass.hobo_model
24
19
  klass.class_eval(&b)
25
20
  klass.delete_all rescue nil
26
21
  end
27
22
 
28
23
  def user_model(name, &b)
29
- klass = Object.const_set(name, Class.new(ActiveRecord::Base))
24
+ klass = Object.const_get(name)
30
25
  klass.hobo_user_model
31
26
  klass.class_eval(&b)
32
27
  klass.delete_all rescue nil
33
28
  end
34
29
 
35
30
  def create_database_sqlite3
36
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
37
- :database => "#{HOME}/test.sqlite3",
38
- :timeout => 5000)
31
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
32
+ :database => "/tmp/hobo_permissions_test.sqlite3",
33
+ :timeout => 5000)
39
34
  end
40
35
 
41
36
  def init
42
- create_database_sqlite3
37
+ Hobo::Model.enable
43
38
  make_models
44
39
  up, down = HoboFields::MigrationGenerator.run
45
40
  ActiveRecord::Migration.class_eval(up)
@@ -47,6 +42,10 @@ module Models
47
42
 
48
43
  def make_models
49
44
 
45
+ [:Response, :Comment, :Request, :Recipe, :Collaboratorship, :Image, :CodeExample, :User].each do |m|
46
+ Object.const_set(m, Class.new(ActiveRecord::Base))
47
+ end
48
+
50
49
  model :Response do
51
50
  fields do
52
51
  body :string
@@ -112,6 +111,9 @@ module Models
112
111
  fields do
113
112
  filename :string
114
113
  end
114
+ has_one :recipe
115
+ def update_permitted?; recipe.user == acting_user end
116
+ def create_permitted?; true end
115
117
  end
116
118
 
117
119
  user_model :User do
@@ -131,4 +133,14 @@ module Models
131
133
 
132
134
  end
133
135
 
134
- end
136
+ end
137
+
138
+ # activerecord 2.3.2 is buggy. It requires a connection before we can
139
+ # load hobo. see https://gist.github.com/90542/0417ee6e71f0bed287824d47163c0e34ff4dc321
140
+ # otherwise, this line should be in Models.init
141
+ Models.create_database_sqlite3
142
+ require 'hobosupport'
143
+ require 'hobofields'
144
+ require 'hobo'
145
+
146
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hobo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Locke
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-12-09 00:00:00 +00:00
12
+ date: 2009-05-14 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - "="
22
22
  - !ruby/object:Gem::Version
23
- version: 0.8.5
23
+ version: 0.8.6
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: hobofields
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - "="
32
32
  - !ruby/object:Gem::Version
33
- version: 0.8.5
33
+ version: 0.8.6
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: rails
@@ -64,11 +64,9 @@ extra_rdoc_files:
64
64
  - lib/active_record/association_collection.rb
65
65
  - lib/active_record/association_proxy.rb
66
66
  - lib/active_record/association_reflection.rb
67
- - lib/extensions/test_case.rb
68
67
  - lib/hobo/accessible_associations.rb
69
68
  - lib/hobo/authentication_support.rb
70
69
  - lib/hobo/bundle.rb
71
- - lib/hobo/composite_model.rb
72
70
  - lib/hobo/controller.rb
73
71
  - lib/hobo/dev_controller.rb
74
72
  - lib/hobo/dryml/dryml_builder.rb
@@ -106,7 +104,6 @@ extra_rdoc_files:
106
104
  - lib/hobo/model.rb
107
105
  - lib/hobo/model_controller.rb
108
106
  - lib/hobo/model_router.rb
109
- - lib/hobo/model_support.rb
110
107
  - lib/hobo/permissions/associations.rb
111
108
  - lib/hobo/permissions.rb
112
109
  - lib/hobo/rapid_helper.rb
@@ -116,6 +113,7 @@ extra_rdoc_files:
116
113
  - lib/hobo/scopes/named_scope_extensions.rb
117
114
  - lib/hobo/scopes.rb
118
115
  - lib/hobo/static_tags
116
+ - lib/hobo/tasks/rails.rb
119
117
  - lib/hobo/undefined.rb
120
118
  - lib/hobo/undefined_access_error.rb
121
119
  - lib/hobo/user.rb
@@ -125,8 +123,6 @@ extra_rdoc_files:
125
123
  - LICENSE.txt
126
124
  - README
127
125
  - tasks/environments.rake
128
- - tasks/fix_dryml.rake
129
- - tasks/generate_tag_reference.rake
130
126
  - tasks/hobo_tasks.rake
131
127
  files:
132
128
  - bin/hobo
@@ -139,11 +135,9 @@ files:
139
135
  - lib/active_record/association_collection.rb
140
136
  - lib/active_record/association_proxy.rb
141
137
  - lib/active_record/association_reflection.rb
142
- - lib/extensions/test_case.rb
143
138
  - lib/hobo/accessible_associations.rb
144
139
  - lib/hobo/authentication_support.rb
145
140
  - lib/hobo/bundle.rb
146
- - lib/hobo/composite_model.rb
147
141
  - lib/hobo/controller.rb
148
142
  - lib/hobo/dev_controller.rb
149
143
  - lib/hobo/dryml/dryml_builder.rb
@@ -181,7 +175,6 @@ files:
181
175
  - lib/hobo/model.rb
182
176
  - lib/hobo/model_controller.rb
183
177
  - lib/hobo/model_router.rb
184
- - lib/hobo/model_support.rb
185
178
  - lib/hobo/permissions/associations.rb
186
179
  - lib/hobo/permissions.rb
187
180
  - lib/hobo/rapid_helper.rb
@@ -191,6 +184,7 @@ files:
191
184
  - lib/hobo/scopes/named_scope_extensions.rb
192
185
  - lib/hobo/scopes.rb
193
186
  - lib/hobo/static_tags
187
+ - lib/hobo/tasks/rails.rb
194
188
  - lib/hobo/undefined.rb
195
189
  - lib/hobo/undefined_access_error.rb
196
190
  - lib/hobo/user.rb
@@ -274,8 +268,6 @@ files:
274
268
  - taglibs/rapid_support.dryml
275
269
  - taglibs/rapid_user_pages.dryml
276
270
  - tasks/environments.rake
277
- - tasks/fix_dryml.rake
278
- - tasks/generate_tag_reference.rake
279
271
  - tasks/hobo_tasks.rake
280
272
  - test/generators/test_generator_helper.rb
281
273
  - test/generators/test_helper.rb
@@ -317,7 +309,6 @@ signing_key:
317
309
  specification_version: 2
318
310
  summary: The web app builder for Rails
319
311
  test_files:
320
- - test/dryml/complilation_test.rb
321
312
  - test/generators/test_generator_helper.rb
322
313
  - test/generators/test_helper.rb
323
314
  - test/generators/test_hobo_model_controller_generator.rb
@@ -1,129 +0,0 @@
1
-
2
- class Test::Unit::TestCase
3
-
4
- def self.fixture_objects(model, *names)
5
- fixtures model
6
- names.each do |name|
7
- class_eval "def #{name}; #{model}(:#{name}); end"
8
- end
9
- end
10
-
11
- protected
12
-
13
- module HoboTesting
14
-
15
- class HoboHelpers
16
-
17
- def urlb
18
- "http://example.com"
19
- end
20
- end
21
-
22
- attr_reader :current_user
23
-
24
- def is_redirected_to(x)
25
- url = x.is_a?(String) ? x : object_url(x)
26
- assert_response :redirect
27
- assert_redirected_to(url)
28
- follow_redirect!
29
- assert_response :success
30
- end
31
-
32
- def logs_in_as(user, password)
33
- @current_user = user
34
- post login_url(user), :login => user.login, :password => password
35
- assert_response :redirect, "#{user.login} failed to log in"
36
- get homepage_url
37
- assert_response :success
38
- end
39
-
40
- def visits(obj, action=nil, params={})
41
- get object_url(obj, action, params)
42
- assert_response :success
43
- end
44
-
45
- def cant_visit(obj, action=nil)
46
- get object_url(obj, action)
47
- assert_response :forbidden
48
- end
49
-
50
- def creates(klass, params)
51
- replace_objects_in_params!(params)
52
- post object_url(klass), klass.name.underscore => params
53
- new_obj = assigns["this"]
54
- flunk "validation errors: #{new_obj.errors.full_messages.join("\n")}" unless new_obj.errors.empty?
55
- assert_response :redirect
56
- new_obj
57
- end
58
-
59
- def deletes(object)
60
- post object_url(object, "destroy")
61
- assert_raise(ActiveRecord::RecordNotFound) { object.class.find(object.id) }
62
- assert_response :redirect
63
- end
64
-
65
- def cant_create(klass, params)
66
- replace_objects_in_params!(params)
67
- post object_url(klass), klass.name.underscore => params
68
- assert_response :forbidden
69
- end
70
-
71
- def can_see(s)
72
- assert_select("body", Regexp.new(s.split.map { |w| Regexp.escape(w) }.join("\s*")),
73
- current_should("be able to see: #{s}"))
74
- end
75
-
76
- alias_method :sees, :can_see
77
-
78
- def cant_see(s)
79
- assert_select("body", { :text => Regexp.new(s.split.map { |w| Regexp.escape(w) }.join("\s*")), :count => 0 },
80
- current_should("not be able to see: #{s}"))
81
- end
82
-
83
- def creates_and_visits(klass, params)
84
- new_obj = creates(klass, params)
85
- visits(new_obj)
86
- new_obj
87
- end
88
-
89
- def calls_method(object, method, params={})
90
- post object_url(object, method), params
91
- assert_response :success
92
- end
93
-
94
- def current_should(s)
95
- "#{current_user.login} should #{s}"
96
- end
97
-
98
- def object_url(obj, action=nil, *param_hashes)
99
- HoboHelpers.new.send(:object_url, obj, action, *param_hashes)
100
- end
101
-
102
- def replace_objects_in_params!(hash)
103
- hash.each do |k,v|
104
- if v.is_a? ActiveRecord::Base
105
- hash[k] = "@" + v.typed_id
106
- elsif v.is_a? Hash
107
- replace_objects_in_params!(v)
108
- end
109
- end
110
- end
111
-
112
- end
113
-
114
- def new_session
115
- open_session do |sess|
116
- sess.extend(HoboTesting)
117
- session_opened(sess) if respond_to? :session_opened
118
- yield sess if block_given?
119
- end
120
- end
121
-
122
- def new_session_as(person, password)
123
- new_session do |sess|
124
- sess.logs_in_as(person, password)
125
- yield sess if block_given?
126
- end
127
- end
128
-
129
- end
@@ -1,73 +0,0 @@
1
- module Hobo
2
-
3
- class CompositeModel
4
-
5
- include ModelSupport
6
-
7
- class << self
8
-
9
- def find(id)
10
- ids = id.split('_')
11
- new(*ids.map_with_index{|id, i| @models[i].constantize.find(id)})
12
- end
13
-
14
- def compose(*models)
15
- @models = models.map &it.to_s.camelize
16
- attr_reader *models
17
- CompositeModel.composites ||= {}
18
- CompositeModel.composites[@models.sort] = self.name
19
-
20
- Hobo.register_model(self)
21
- end
22
-
23
- attr_accessor :composites
24
-
25
- attr_reader :models
26
-
27
- def new_for(objects)
28
- classes = objects.map{|o| o.class.name}.sort
29
- composite_class = CompositeModel.composites[classes].constantize rescue
30
- (raise ArgumentError, "No composite model for #{classes.inspect}")
31
- composite_class.new(*objects)
32
- end
33
-
34
- end
35
-
36
-
37
- def initialize(*objects)
38
- objects.each do |obj|
39
- raise ArgumentError, "invalid objects for composition: #{objects.inspect}" unless
40
- obj.class.name.in? self.class.models
41
- instance_variable_set("@#{obj.class.name.underscore}", obj)
42
- end
43
- end
44
-
45
-
46
- def has_hobo_method?(name)
47
- respond_to?(name)
48
- end
49
-
50
-
51
- def compose_with(object, use=nil)
52
- self_classes = use ? use.models : self.class.models
53
- from_self = (self_classes - [object.class.name]).map {|classname| send(classname.underscore)}
54
- CompositeModel.new_for(from_self + [object])
55
- end
56
-
57
-
58
- def typed_id
59
- "#{self.class.name.underscore}:#{id}"
60
- end
61
-
62
-
63
- def id
64
- objects = self.class.models.map {|m| instance_variable_get("@#{m.underscore}")}
65
- objects.*.id.join("_")
66
- end
67
-
68
- alias_method :to_param, :id
69
-
70
- end
71
-
72
- end
73
-