mongoid-included 0.3.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@
3
3
  .rvmrc
4
4
  Gemfile.lock
5
5
  pkg/*
6
+ .yardoc/*
data/.rspec CHANGED
@@ -1 +1 @@
1
- --color --format nested --fail-fast
1
+ --color --format documentation
data/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  Mongoid::Included
2
2
  ====================
3
3
 
4
- Helper module to embed documents using the parent's namespace while preserving url helpers consistency. This is useful to organize your project if you heavily rely on embedded documents. This gem concerns the issue 1429 of rails repository: https://github.com/rails/rails/issues/1429
5
- Works with [Mongoid 2.0](https://github.com/mongoid/mongoid) and ActiveModel 3.1.0.beta1.
4
+ Helper module to embed documents using the parent's namespace while preserving url helpers consistency.
5
+ This is useful to organize your project if you heavily rely on embedded documents.
6
+ This gem concerns the issue 1429 of rails repository: https://github.com/rails/rails/issues/1429
7
+ Works with [Mongoid 2.4](https://github.com/mongoid/mongoid) and ActiveModel 3.2.0.
6
8
 
7
9
  Installation
8
10
  ------------
@@ -39,7 +41,6 @@ Example
39
41
 
40
42
  class Invoice
41
43
  include Mongoid::Document
42
- include Mongoid::DocumentInclusion
43
44
 
44
45
  includes_many :items
45
46
  end
@@ -49,14 +50,13 @@ Example
49
50
 
50
51
  class Invoice::Item
51
52
  include Mongoid::Document
52
- include Mongoid::DocumentInclusion
53
53
 
54
54
  included_in :invoice
55
55
  end
56
56
  # This will generate the following code:
57
57
  extend ActiveModel::Naming
58
58
  # Overriding .model_name so rails recognizes the class as __Item__ and generate more convenient urls.
59
- def model_name
59
+ def self.model_name
60
60
  if self.parent != Object
61
61
  ActiveModel::Name.new(self, self.parent)
62
62
  else
data/Rakefile CHANGED
@@ -4,19 +4,10 @@ require 'bundler'
4
4
  require "rspec"
5
5
  require 'rspec/core/rake_task'
6
6
 
7
- RSpec::Core::RakeTask.new("spec:functional") do |spec|
8
- spec.rspec_opts = %w(--format progress)
9
- spec.pattern = "spec/functional/**/*_spec.rb"
7
+ RSpec::Core::RakeTask.new(:spec) do |spec|
8
+ spec.rspec_opts = %w(--format documentation)
9
+ spec.pattern = "spec/**/*_spec.rb"
10
10
  end
11
11
 
12
12
  task :default => :spec
13
13
  task :test => :spec
14
-
15
- require 'rake/rdoctask'
16
- require "mongoid-included/version"
17
- Rake::RDocTask.new do |rdoc|
18
- rdoc.rdoc_dir = 'rdoc'
19
- rdoc.title = "mongoid-included #{Mongoid::Mirrored::VERSION}"
20
- rdoc.rdoc_files.include('README*')
21
- rdoc.rdoc_files.include('lib/**/*.rb')
22
- end
data/changelog.txt ADDED
@@ -0,0 +1,8 @@
1
+ # v1.0.0
2
+ - Updating dependency to ActiveModel 3.2
3
+ - Getting rid of +Embedded::Name+, since partial_path will be deprecated in ActiveModel
4
+ - Overriding +Model._to_partial_path+, originally implemented in ActiveModel::Conversion
5
+ - :skip_path_pluralization option added for #included_in. Allows conventional use of partial paths, without pluralization.
6
+
7
+ # v0.3.1
8
+ - Allowing Mongoid 3.0 support in Gemspec
@@ -1,6 +1,5 @@
1
1
  class Invoice
2
2
  include Mongoid::Document
3
- include Mongoid::DocumentInclusion
4
3
  field :title
5
4
 
6
5
  includes_many :items
@@ -1,6 +1,5 @@
1
1
  class Invoice::Item
2
2
  include Mongoid::Document
3
- include Mongoid::DocumentInclusion
4
3
 
5
4
  field :description
6
5
 
@@ -1,6 +1,5 @@
1
1
  class Invoice::User
2
2
  include Mongoid::Document
3
- include Mongoid::DocumentInclusion
4
3
 
5
4
  field :name
6
5
 
data/example/readme.txt CHANGED
@@ -5,4 +5,4 @@ the parent's document folder
5
5
 
6
6
  This conventions respects url generation,
7
7
  correct parameter names in form building
8
- and template locations, incluing partials
8
+ and template locations, incluing partials.
@@ -1,100 +1,149 @@
1
- require 'mongoid-included/embedded_name'
2
1
  require 'mongoid-included/inclusion_errors'
3
2
  module Mongoid
4
3
  module DocumentInclusion
4
+ # Adds convenience methods to embed Mongoid documents into others using namespaces.
5
+ # It also provides methods to define their inverse relation, on root documents.
5
6
  extend ActiveSupport::Concern
6
7
 
7
8
  included do
9
+ # @return [ Array ] list of classes in which a class is included in an +Embedded Relation+.
8
10
  cattr_accessor :included_by
11
+ # @return [ Array ] list of classes a given class includes in a +Many Relation+.
9
12
  cattr_accessor :including_many
13
+ # @return [ Array ] list of classes a given class includes in a +One Relation+.
10
14
  cattr_accessor :including_one
15
+
16
+ self.included_by, self.including_many, self.including_one = [], [], []
11
17
  end
12
18
 
13
19
  module ClassMethods
14
- def included_in(_model, args = {})
15
- if args && args[:class_name]
16
- _class_name = args[:class_name]
20
+ # Facade for Mongoid::Relations::Macros.embeded_in
21
+ # @param [ Symbol ] relation_name name for the parent association
22
+ # @param [ Hash ] args (see Mongoid::Relations::Macros.embeded_in)
23
+ # @option args [ true, false ] :skip_path_pluralization If Partial Paths should be
24
+ # kept as default, using the namespace in singular form
25
+ #
26
+ # @example Skipping pluralization
27
+ # class Entry::Image
28
+ # included_in :entry, :skip_path_pluralization => true
29
+ # image.to_partial_path #=> "entry/images/image"
30
+ #
31
+ # @example With pluralization. This seems a more natural fit for partials placement.
32
+ # class Entry::Image
33
+ # included_in :entry
34
+ # image.to_partial_path #=> "entries/images/image"
35
+ def included_in(relation_name, args = {})
36
+ @skip_path_pluralization = args.delete(:skip_path_pluralization)
37
+
38
+ relation_klass = if args[:class_name]
39
+ infer_klass(args[:class_name])
17
40
  else
18
- _class_name = _model
19
- end
41
+ infer_klass(relation_name)
42
+ end
43
+
44
+ raise NotMongoidDocument, "Parent must be Mongoid::Document" unless has_mongoid? self.parent
45
+ raise DocumentAlreadyIncluded, "Document already included" if (included_by | [ relation_klass ]).size > 1
20
46
 
21
- raise NotMongoidDocument, "Parent must be Mongoid::Document" unless _mongoid_document? self.parent
22
- raise DocumentAlreadyIncluded, "Document already included" if (!included_by.blank? && included_by!=[_model_klass(_class_name)])
23
- embedded_in _model, args
47
+ embedded_in relation_name, args
48
+ self.included_by |= [ relation_klass ]
24
49
 
25
- self.included_by ||= []
26
- self.included_by << _model_klass(_class_name) unless included_by.include? _model_klass(_class_name)
27
50
  self.extend ActiveModel::Naming
28
51
  _overwrite_model_name
29
52
  end
30
53
 
31
- def includes_many(_model, args = {})
32
- if args && args[:class_name]
33
- _class_name = args[:class_name]
34
- self.including_many ||= []
35
- self.including_many << _model_klass(_class_name) unless including_many.include? _model_klass(_class_name)
54
+ # Facade for Mongoid::Relations::Macros.embeds_many
55
+ # @param [ Symbol ] relation_name Name for the child association
56
+ # @param [ Hash ] args (see Mongoid::Relations::Macros.embeds_many)
57
+ def includes_many(relation_name, args = {})
58
+ relation_klass = if args[:class_name]
59
+ infer_klass(args[:class_name])
36
60
  else
37
- _verify_dependencies(_model)
38
- _class_name = _included_klass_name(_model)
39
- self.including_many ||= []
40
- self.including_many << _included_klass(_model) unless including_many.include? _included_klass(_model)
61
+ klass_to_include(relation_name)
41
62
  end
42
- embeds_many _model, args.merge(:class_name => _class_name )
63
+
64
+ verify_inclusion_dependencies(relation_klass)
65
+ self.including_many |= [ relation_klass ]
66
+
67
+ embeds_many relation_name, args.merge(:class_name => relation_klass.name )
43
68
  end
44
69
 
45
- def includes_one(_model, args = {})
46
- if args && args[:class_name]
47
- _class_name = args[:class_name]
48
- self.including_one ||= []
49
- self.including_one << _model_klass(_class_name) unless including_one.include? _model_klass(_class_name)
70
+
71
+ # Facade for Mongoid::Relations::Macros.embeds_one
72
+ # @param [ Symbol ] _model Name for the association
73
+ # @param [ Hash ] args (see Mongoid::Relations::Macros.embeds_one)
74
+ def includes_one(relation_name, args = {})
75
+ relation_klass = if args[:class_name]
76
+ infer_klass(args[:class_name])
50
77
  else
51
- _verify_dependencies(_model)
52
- _class_name = _included_klass_name(_model)
53
- self.including_one ||= []
54
- self.including_one << _included_klass(_model) unless including_one.include? _included_klass(_model)
78
+ klass_to_include(relation_name)
55
79
  end
56
- embeds_one _model, args.merge(:class_name => _class_name)
80
+
81
+ verify_inclusion_dependencies(relation_klass)
82
+ self.including_one |= [ relation_klass ]
83
+
84
+ embeds_one relation_name, args.merge(:class_name => relation_klass.name )
57
85
  end
58
86
 
59
87
  private
60
88
 
89
+ # Overrides +ActiveModel.model_name+ and +Model._to_partial_path+
90
+ # for ActiveModel compliant classes.
91
+ # @note This method requires ActiveModel ~> 3.2. This release deprecates
92
+ # ActiveModel::Naming#partial_path in favor or model.to_partial_path.
93
+ # @since 1.0.0
61
94
  def _overwrite_model_name
62
- self.class_eval <<-EOF
63
- def self.model_name
64
- @_model_name ||=begin
65
- if self.parent != Object
66
- Mongoid::EmbeddedName.new(self, self.parent)
67
- else
68
- namespace = self.parents.detect { |n| n.respond_to?(:_railtie) }
69
- ActiveModel::Name.new(self, namespace)
95
+ if self.parent != Object
96
+ self.class_eval <<-EOF
97
+ def self.model_name
98
+ @_model_name ||=begin
99
+ ActiveModel::Name.new(self, self.parent)
70
100
  end
71
101
  end
102
+ EOF
103
+ unless @skip_path_pluralization
104
+ self.class_eval <<-EOF
105
+ def self._to_partial_path
106
+ @_to_partial_path ||= begin
107
+ plural_namespace = ActiveSupport::Inflector.tableize(self.parent).freeze
108
+ plural_element = ActiveSupport::Inflector.pluralize(model_name.element)
109
+ path = [plural_namespace, plural_element, model_name.element].join("/").freeze
110
+ end
111
+ end
112
+ EOF
72
113
  end
73
- EOF
74
- end
75
-
76
- def _model_klass_name(_model)
77
- _model.to_s.classify
114
+ end
78
115
  end
79
116
 
80
- def _model_klass(_model)
81
- _model.to_s.classify.constantize
117
+ # Returns the class for a given name
118
+ # @param [ Symbol ] _model the relation name
119
+ # @return [ Object <Mongoid::Document> ] the model class
120
+ # @example A relation named :entry
121
+ # infer_klass("Entry::Image") #=> Entry::Image
122
+ def infer_klass(klass_name)
123
+ klass_name.to_s.classify.constantize
82
124
  end
83
125
 
84
- def _included_klass_name(_model)
85
- "#{self}::#{_model_klass_name(_model)}"
126
+ # Returns the class for a given relation
127
+ # @param [ Symbol ] relation_name the relation name
128
+ # @return [ Class ] the model class
129
+ # @example A relation named :comments for an Entry class
130
+ # klass_to_include(:comments) #=> Entry::Comment
131
+ def klass_to_include(relation_name)
132
+ "#{self}/#{relation_name}".classify.constantize
86
133
  end
87
134
 
88
- def _included_klass(_model)
89
- "#{self}::#{_model_klass_name(_model)}".constantize
90
- end
91
-
92
- def _mongoid_document?(_model)
93
- _model.included_modules.include?(Mongoid::Document)
135
+ # If relation name targets a Mongoid Document
136
+ # @param [ Symbol ] _model the relation name
137
+ # @return [ true, false ] if relation is a Mongoid::Document
138
+ def has_mongoid?(embeding_target)
139
+ embeding_target < Mongoid::Document
94
140
  end
95
141
 
96
- def _verify_dependencies(_model)
97
- raise NotMongoidDocument, "Child must be Mongoid::Document" unless _mongoid_document? _model_klass(_included_klass_name(_model))
142
+ # Verifies if an association can be included
143
+ # @param [ Symbol ] _model the relation name
144
+ # @raise [ NotMongoidDocument ] if relation is not a Mongoid::Document
145
+ def verify_inclusion_dependencies(relation_klass)
146
+ raise NotMongoidDocument, "Child must be Mongoid::Document" unless has_mongoid? relation_klass
98
147
  end
99
148
  end
100
149
  end
@@ -1,5 +1,5 @@
1
1
  module Mongoid
2
2
  module Included
3
- VERSION = "0.3.2"
3
+ VERSION = "1.1.0"
4
4
  end
5
5
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.authors = ["Alexandre Angelim"]
10
10
  s.email = %q{angelim@angelim.com.br}
11
11
  s.homepage = %q{http://github.com/angelim/mongoid-included}
12
- s.summary = %q{Included namespaces documents for Mongoid}
12
+ s.summary = %q{Included namespaced documents for Mongoid}
13
13
  s.description = %q{Helper to facilitate inclusion of namespaced documents in another Mongoid Document}
14
14
 
15
15
  s.rubyforge_project = "mongoid-included"
@@ -19,8 +19,11 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
21
 
22
- s.add_runtime_dependency(%q<mongoid>, [">= 2.0"])
22
+ s.add_runtime_dependency(%q<mongoid>, [">= 2.4"])
23
+ s.add_runtime_dependency(%q<activemodel>, ["~> 3.2"])
23
24
  s.add_development_dependency("rspec", ["~> 2.6.0"])
24
25
  s.add_development_dependency("bson_ext", ["~> 1.3"])
26
+ s.add_development_dependency "rake", ["~> 0.9"]
27
+ s.add_development_dependency "yard", ["~> 0.7.4"]
25
28
 
26
29
  end
@@ -1,5 +1,6 @@
1
1
  class Invoice
2
2
  includes_many :items
3
+ includes_many :price_lists
3
4
  includes_one :user, :inverse_of => :invoice
4
5
  includes_one :other_user, :class_name => "Invoice::User", :inverse_of => :user_invoice
5
6
  includes_many :other_items, :class_name => "Invoice::Item"
@@ -13,4 +14,8 @@ end
13
14
  class Invoice::User
14
15
  included_in :invoice, :inverse_of => :user
15
16
  included_in :user_invoice, :class_name => "Invoice", :inverse_of => :other_user
17
+ end
18
+
19
+ class Invoice::PriceList
20
+ included_in :invoice, :inverse_of => :price_lists, :skip_path_pluralization => true
16
21
  end
@@ -0,0 +1,5 @@
1
+ class Invoice::PriceList
2
+ include Mongoid::Document
3
+
4
+ field :value, :type => Float
5
+ end
data/spec/spec_helper.rb CHANGED
@@ -14,6 +14,7 @@ MODELS.each do |_model|
14
14
  end
15
15
  require 'models/invoice'
16
16
  require 'models/invoice/item'
17
+ require 'models/invoice/price_list'
17
18
  require 'models/invoice/user'
18
19
  require 'models/invoice/not_included'
19
20
  require 'models/inclusion'
@@ -9,9 +9,15 @@ describe "Child Model" do
9
9
  it "strips namespace from #route_key" do
10
10
  Invoice::Item.model_name.route_key.should == "items"
11
11
  end
12
-
13
- it "pluralize namespace in #partial_path" do
14
- Invoice::Item.model_name.partial_path.should == "invoices/items/item"
12
+ context "when pluralizing partial path" do
13
+ it "returns partial path with pluralized embedding class" do
14
+ Invoice::Item.new.to_partial_path.should == "invoices/items/item"
15
+ end
16
+ end
17
+ context "when skipping partial path pluralization" do
18
+ it "returns partial path with singular embedding class" do
19
+ Invoice::PriceList.new.to_partial_path.should == "invoice/price_lists/price_list"
20
+ end
15
21
  end
16
22
 
17
23
  it "delegates options to mongoid relation macro" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongoid-included
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,23 +9,34 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-26 00:00:00.000000000 -02:00
12
+ date: 2012-01-27 00:00:00.000000000 -02:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: mongoid
17
- requirement: &2155089800 !ruby/object:Gem::Requirement
17
+ requirement: &2153298320 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
21
21
  - !ruby/object:Gem::Version
22
- version: '2.0'
22
+ version: '2.4'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *2155089800
25
+ version_requirements: *2153298320
26
+ - !ruby/object:Gem::Dependency
27
+ name: activemodel
28
+ requirement: &2153297520 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *2153297520
26
37
  - !ruby/object:Gem::Dependency
27
38
  name: rspec
28
- requirement: &2155089180 !ruby/object:Gem::Requirement
39
+ requirement: &2153297020 !ruby/object:Gem::Requirement
29
40
  none: false
30
41
  requirements:
31
42
  - - ~>
@@ -33,10 +44,10 @@ dependencies:
33
44
  version: 2.6.0
34
45
  type: :development
35
46
  prerelease: false
36
- version_requirements: *2155089180
47
+ version_requirements: *2153297020
37
48
  - !ruby/object:Gem::Dependency
38
49
  name: bson_ext
39
- requirement: &2155088700 !ruby/object:Gem::Requirement
50
+ requirement: &2153296140 !ruby/object:Gem::Requirement
40
51
  none: false
41
52
  requirements:
42
53
  - - ~>
@@ -44,7 +55,29 @@ dependencies:
44
55
  version: '1.3'
45
56
  type: :development
46
57
  prerelease: false
47
- version_requirements: *2155088700
58
+ version_requirements: *2153296140
59
+ - !ruby/object:Gem::Dependency
60
+ name: rake
61
+ requirement: &2153295100 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ~>
65
+ - !ruby/object:Gem::Version
66
+ version: '0.9'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *2153295100
70
+ - !ruby/object:Gem::Dependency
71
+ name: yard
72
+ requirement: &2153310960 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.7.4
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: *2153310960
48
81
  description: Helper to facilitate inclusion of namespaced documents in another Mongoid
49
82
  Document
50
83
  email: angelim@angelim.com.br
@@ -60,6 +93,7 @@ files:
60
93
  - LICENSE
61
94
  - README.md
62
95
  - Rakefile
96
+ - changelog.txt
63
97
  - example/controllers/invoices/items_controller.rb
64
98
  - example/controllers/invoices/user_controller.rb
65
99
  - example/controllers/invoices_controller.rb
@@ -74,7 +108,6 @@ files:
74
108
  - example/views/layouts/application.html.erb
75
109
  - lib/mongoid-included.rb
76
110
  - lib/mongoid-included/document_inclusion.rb
77
- - lib/mongoid-included/embedded_name.rb
78
111
  - lib/mongoid-included/inclusion_errors.rb
79
112
  - lib/mongoid-included/version.rb
80
113
  - log/development.log
@@ -85,6 +118,7 @@ files:
85
118
  - spec/models/invoice.rb
86
119
  - spec/models/invoice/item.rb
87
120
  - spec/models/invoice/not_included.rb
121
+ - spec/models/invoice/price_list.rb
88
122
  - spec/models/invoice/user.rb
89
123
  - spec/spec_helper.rb
90
124
  - spec/unit/included_spec.rb
@@ -113,7 +147,7 @@ rubyforge_project: mongoid-included
113
147
  rubygems_version: 1.6.2
114
148
  signing_key:
115
149
  specification_version: 3
116
- summary: Included namespaces documents for Mongoid
150
+ summary: Included namespaced documents for Mongoid
117
151
  test_files:
118
152
  - spec/functional/invoice.rb
119
153
  - spec/functional/item.rb
@@ -121,6 +155,7 @@ test_files:
121
155
  - spec/models/invoice.rb
122
156
  - spec/models/invoice/item.rb
123
157
  - spec/models/invoice/not_included.rb
158
+ - spec/models/invoice/price_list.rb
124
159
  - spec/models/invoice/user.rb
125
160
  - spec/spec_helper.rb
126
161
  - spec/unit/included_spec.rb
@@ -1,43 +0,0 @@
1
- module Mongoid
2
- class EmbeddedName < String
3
- attr_reader :singular, :plural, :element, :collection, :partial_path, :route_key, :param_key, :i18n_key
4
- alias_method :cache_key, :collection
5
-
6
- def initialize(klass, namespace, pluralize_namespace = true)
7
- name ||= klass.name
8
- super(name)
9
- @unnamespaced = name.sub(/^#{namespace.name}::/, '') if namespace
10
- @klass = klass
11
- @singular = _singularize(name).freeze
12
- @singular_namespace = _singularize(namespace.name).freeze
13
- @plural = ActiveSupport::Inflector.pluralize(@singular).freeze
14
- @plural_namespace = ActiveSupport::Inflector.pluralize(@singular_namespace).freeze
15
- @element = ActiveSupport::Inflector.underscore(ActiveSupport::Inflector.demodulize(name)).freeze
16
- @human = ActiveSupport::Inflector.humanize(@element).freeze
17
- @collection = ActiveSupport::Inflector.tableize(name).freeze
18
- @partial_path = "#{@collection.sub(@singular_namespace, @plural_namespace)}/#{@element}".freeze
19
- @param_key = _singularize(@unnamespaced).freeze
20
- @route_key = ActiveSupport::Inflector.pluralize(@param_key).freeze
21
- @i18n_key = name.underscore.to_sym
22
- end
23
-
24
- def human(options={})
25
- return @human unless @klass.respond_to?(:lookup_ancestors) &&
26
- @klass.respond_to?(:i18n_scope)
27
-
28
- defaults = @klass.lookup_ancestors.map do |klass|
29
- klass.model_name.i18n_key
30
- end
31
-
32
- defaults << options[:default] if options[:default]
33
- defaults << @human
34
-
35
- options = {:scope => [@klass.i18n_scope, :models], :count => 1, :default => defaults}.merge(options.except(:default))
36
- I18n.translate(defaults.shift, options)
37
- end
38
-
39
- def _singularize(string, replacement='_')
40
- ActiveSupport::Inflector.underscore(string).tr('/', replacement)
41
- end
42
- end
43
- end