espresso 0.1.12 → 0.2.1

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 (52) hide show
  1. data/.gitignore +4 -2
  2. data/README.rdoc +18 -4
  3. data/Rakefile +33 -7
  4. data/VERSION +1 -1
  5. data/espresso.gemspec +59 -28
  6. data/lib/espresso.rb +36 -19
  7. data/lib/espresso/collection.rb +44 -0
  8. data/lib/espresso/collection/searchlogic.rb +17 -0
  9. data/lib/espresso/collection/will_paginate.rb +19 -0
  10. data/lib/espresso/concern.rb +37 -0
  11. data/lib/espresso/controller.rb +17 -0
  12. data/lib/espresso/controller/inherited_resources.rb +110 -0
  13. data/lib/espresso/deprecated.rb +19 -0
  14. data/lib/espresso/deprecated/resources.rb +11 -0
  15. data/lib/espresso/extensions/action_controller.rb +6 -0
  16. data/lib/espresso/extensions/action_view.rb +6 -0
  17. data/lib/espresso/extensions/active_record.rb +6 -0
  18. data/lib/espresso/extensions/all.rb +6 -0
  19. data/lib/espresso/{haml.rb → extensions/haml.rb} +4 -2
  20. data/lib/espresso/extensions/has_scope.rb +13 -0
  21. data/lib/espresso/extensions/inherited_resources.rb +15 -0
  22. data/lib/espresso/extensions/searchlogic.rb +14 -0
  23. data/lib/espresso/extensions/will_paginate.rb +14 -0
  24. data/lib/espresso/model.rb +22 -66
  25. data/lib/espresso/model/inherited_resources.rb +20 -0
  26. data/lib/espresso/view.rb +261 -0
  27. data/lib/espresso/{action_view → view}/form_builder.rb +3 -1
  28. data/lib/espresso/view/has_scope.rb +23 -0
  29. data/lib/espresso/view/inherited_resources.rb +72 -0
  30. data/lib/espresso/view/searchlogic.rb +33 -0
  31. data/lib/espresso/view/will_paginate.rb +35 -0
  32. data/test/espresso_collection_test.rb +6 -0
  33. data/test/espresso_controller_test.rb +1 -0
  34. data/test/espresso_extensions_haml_test.rb +19 -0
  35. data/test/espresso_model_test.rb +26 -0
  36. data/test/espresso_test.rb +1 -3
  37. data/test/espresso_view_has_scope_test.rb +11 -0
  38. data/test/espresso_view_test.rb +46 -0
  39. data/test/espresso_view_will_paginate_test.rb +9 -0
  40. data/test/example_model.rb +23 -0
  41. data/test/test_helper.rb +42 -1
  42. metadata +73 -33
  43. data/lib/espresso/action_controller.rb +0 -7
  44. data/lib/espresso/action_view.rb +0 -21
  45. data/lib/espresso/action_view/navigation.rb +0 -100
  46. data/lib/espresso/action_view/resources.rb +0 -59
  47. data/lib/espresso/action_view/scopes.rb +0 -38
  48. data/lib/espresso/action_view/stats.rb +0 -54
  49. data/lib/espresso/locales/en.yml +0 -6
  50. data/lib/espresso/locales/ru.yml +0 -11
  51. data/lib/espresso/resources.rb +0 -79
  52. data/lib/espresso/resources_helpers.rb +0 -24
@@ -0,0 +1,110 @@
1
+ require 'espresso/controller'
2
+ require 'inherited_resources'
3
+ require 'active_support/core_ext/class/inheritable_attributes'
4
+
5
+ module Espresso
6
+ module Controller
7
+ mattr_accessor :default_resources_options
8
+ self.default_resources_options = {
9
+ :enhance => true
10
+ }
11
+
12
+ included do
13
+ helper_method :resource?, :collection?
14
+ end
15
+
16
+ module ClassMethods
17
+ # Includes default CRUD actions in ActionController::Base using InheritedResources, enhance
18
+ # @param [Hash] options options of resources
19
+ # @option options :enhance (true) whether to enhance resource controller with Espresso-provided helpers or not
20
+ def resources(options = {})
21
+ options.reverse_merge!(Espresso::Controller.default_resources_options)
22
+
23
+ ::InheritedResources::Base.inherit_resources(self)
24
+ initialize_resources_class_accessors!
25
+ create_resources_url_helpers!
26
+
27
+ if options[:enhance]
28
+ include Espresso::Controller::InheritedResourcesModifications
29
+ end
30
+ end
31
+ end
32
+
33
+ module InstanceMethods
34
+ # Does the action or view have a resource
35
+ # @return [Boolean] having a resource
36
+ def resource?
37
+ resource
38
+ rescue
39
+ false
40
+ end
41
+
42
+ # Does the action or view have a collection of objects
43
+ # @return [Boolean] Having a collection
44
+ def collection?
45
+ collection
46
+ rescue
47
+ false
48
+ end
49
+ end
50
+
51
+ module InheritedResourcesModifications
52
+ extend Espresso::Concern
53
+
54
+ module ClassMethods
55
+ # Adds ability to build feeds for resource’s collections.
56
+ # By default adds Atom feed
57
+ # @example Add Atom feed for #index
58
+ # has_feed :atom
59
+ # @example Add Atom and RSS feed for #index
60
+ # has_feed :atom, :rss
61
+ # @example Add Atom, Rss, and ITunes feed for #index, #list and #archive
62
+ # has_feed :atom, :rss, :itunesfeed, :only => [:index, :list, :archive]
63
+ def has_feed(*args)
64
+ require 'has_scope'
65
+
66
+ options = args.extract_options!
67
+ if options.empty?
68
+ options[:only] = :index
69
+ end
70
+
71
+ class_inheritable_accessor(:feed_formats) unless respond_to?(:feed_formats)
72
+ self.feed_formats = (args.empty? ? [:atom] : args).map(&:to_s)
73
+
74
+ self.feed_formats.each do |format|
75
+ respond_to format, options
76
+ end
77
+
78
+ include FeedScope
79
+ has_scope(:for_feed, options.merge(:default => true,
80
+ :type => :boolean,
81
+ :if => :feed_scope_applicable?))
82
+ end
83
+ end
84
+
85
+ module InstanceMethods
86
+ # Find collection of resources, wrapped with Espresso::Collection
87
+ # @return [Espresso::Collection] collection of resources
88
+ def collection
89
+ get_collection_ivar || set_collection_ivar(end_of_association_chain.collection(params))
90
+ end
91
+
92
+ # Build interpolation options for flash messages
93
+ # @return [Hash, nil] hash of interpolation options if current action has a resource, nil otherwise
94
+ def interpolation_options
95
+ if resource?
96
+ { :resource_title => resource.to_s }
97
+ end
98
+ end
99
+ end
100
+
101
+ module FeedScope
102
+ # Does scope #for_feed applicable to current action?
103
+ # @return [Boolean] if applicable
104
+ def feed_scope_applicable?
105
+ params[:format] && self.class.feed_formats.include?(params[:format].to_sym)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,19 @@
1
+ require 'espresso'
2
+ require 'espresso/model'
3
+
4
+ module Espresso
5
+ ActionView = View
6
+ autoload :Resources, 'espresso/deprecated/resources'
7
+ module Model
8
+ module ClassMethods
9
+ # @deprecated Use model_modifiers instead
10
+ def model_attrs=(attrs)
11
+ model_modifiers=attrs
12
+ end
13
+
14
+ def search_results(page = nil, query = {}, simple_query = nil)
15
+ collection(:page => page, :search => query)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ require 'espresso/extensions/inherited_resources'
2
+
3
+ module Espresso
4
+ module Resources
5
+ extend Espresso::Concern
6
+
7
+ included do
8
+ resources
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ require 'action_controller'
2
+ require 'espresso/controller'
3
+
4
+ class ActionController::Base
5
+ include Espresso::Controller
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'action_view'
2
+ require 'espresso/view'
3
+
4
+ class ActionView::Base
5
+ include Espresso::View
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'active_record'
2
+ require 'espresso/model'
3
+
4
+ class ActiveRecord::Base
5
+ include Espresso::Model
6
+ end
@@ -0,0 +1,6 @@
1
+ require 'espresso'
2
+
3
+ Espresso.uses :inherited_resources
4
+ Espresso.uses :will_paginate
5
+ Espresso.uses :searchlogic
6
+ Espresso.uses :has_scope
@@ -1,7 +1,9 @@
1
1
  require 'haml'
2
2
  require 'haml/buffer'
3
+ require 'espresso/view'
3
4
 
4
5
  class Haml::Buffer
6
+ include Espresso::View
5
7
  # Takes an array of objects and uses the class and id of the first
6
8
  # one to create an attributes hash.
7
9
  # The second object, if present, is used as a prefix,
@@ -14,8 +16,8 @@ class Haml::Buffer
14
16
  class_name = underscore(ref.class)
15
17
  id = "#{class_name}_#{ref.id || 'new'}"
16
18
 
17
- if ref.respond_to?(:model_class)
18
- class_name = ref.model_class
19
+ if ref.respond_to?(:model_modifiers)
20
+ class_name = model_classes(ref)
19
21
  elsif prefix
20
22
  class_name = "#{prefix}_#{class_name}"
21
23
  id = "#{prefix}_#{id}"
@@ -0,0 +1,13 @@
1
+ require 'espresso'
2
+
3
+ begin
4
+ require 'has_scope'
5
+ rescue LoadError
6
+ raise <<-END
7
+ Espresso require has_scope gem to use HasScope extension.
8
+ Please install it by:
9
+ $ gem install has_scope -v 0.4.2
10
+ END
11
+ end
12
+
13
+ require 'espresso/view/has_scope'
@@ -0,0 +1,15 @@
1
+ require 'espresso'
2
+
3
+ begin
4
+ require 'inherited_resources'
5
+ rescue LoadError
6
+ raise <<-END
7
+ Espresso require inherited_resources gem to use InheritedResources extension.
8
+ Please install it by:
9
+ $ gem install inherited_resources -v 1.0.5
10
+ END
11
+ end
12
+
13
+ require 'espresso/model/inherited_resources'
14
+ require 'espresso/view/inherited_resources'
15
+ require 'espresso/controller/inherited_resources'
@@ -0,0 +1,14 @@
1
+ require 'espresso'
2
+
3
+ begin
4
+ require 'searchlogic'
5
+ rescue LoadError
6
+ raise <<-END
7
+ Espresso require searchlogic gem to use Searchlogic extension.
8
+ Please install it by:
9
+ $ gem install searchlogic -v 2.4.12
10
+ END
11
+ end
12
+
13
+ require 'espresso/collection/searchlogic'
14
+ require 'espresso/view/searchlogic'
@@ -0,0 +1,14 @@
1
+ require 'espresso'
2
+
3
+ begin
4
+ require 'will_paginate'
5
+ rescue LoadError
6
+ raise <<-END
7
+ Espresso require will_paginate gem to use WillPaginate extension.
8
+ Please install it by:
9
+ $ gem install will_paginate -v 2.3.12
10
+ END
11
+ end
12
+
13
+ require 'espresso/collection/will_paginate'
14
+ require 'espresso/view/will_paginate'
@@ -1,80 +1,36 @@
1
- require 'searchlogic'
2
- require 'will_paginate'
1
+ require 'espresso'
2
+ require 'active_support/core_ext/class/inheritable_attributes'
3
+ require 'active_support/core_ext/string'
3
4
 
4
5
  module Espresso
5
- # @author Alexander Semyonov
6
6
  module Model
7
- def self.included(model)
8
- super
9
- model.class_eval do
10
- extend ClassMethods
7
+ extend Espresso::Concern
11
8
 
12
- class_inheritable_accessor :model_attrs, :name_field, :per_page
9
+ included do
10
+ class_inheritable_accessor :name_field, :model_modifiers
13
11
 
14
- self.model_attrs = []
15
- self.name_field = :name
16
- self.per_page = 10
17
-
18
- named_scope :for_index, :conditions => '1 = 1'
19
- named_scope :for_feed, :order => 'created_at DESC'
20
- named_scope :for_show, :conditions => '1 = 1'
21
- named_scope :recent, lambda {
22
- {:limit => per_page}
23
- }
24
- end
25
- end
26
-
27
- # String representation of model, based on Model’s name_field
28
- def to_s
29
- send(self.class.name_field).to_s
30
- end
31
-
32
- # Model’s classes, based on Model.model_attrs
33
- def model_class
34
- main_class = "#{::Espresso::MODEL_PREFIX}-#{self.class.name.underscore}"
35
- classes = [main_class] +
36
- self.class.model_attrs.inject([]) do |collection, attribute|
37
- if send("#{attribute}?")
38
- collection << " #{main_class}_#{attribute}"
39
- end
40
- collection
41
- end
42
- classes.join(' ')
12
+ self.name_field = :name
13
+ self.model_modifiers = []
43
14
  end
44
15
 
45
16
  module ClassMethods
46
- # Paginates search results
47
- #
48
- # @param [Integer] page number of resultspage
49
- # @param [Hash] query searchlogic fields (proc’ed named scopes’ names with values)
50
- # @param [String] simple_query params for simple «LIKE '%something%'» searches (e.g. /people?q=Alexander)
51
- # @return [Array] searchlogic object and collection of results
52
- #
53
- # @todo Add an options to paginating
54
- def paginate_found(page = nil, query = {}, simple_query = nil)
55
- query ||= {}
56
- query.merge!(self.parse_simple_query(simple_query)) if simple_query
57
- searchlogic = search(query)
58
- results = searchlogic.paginate(:page => page)
59
- [searchlogic, results]
60
- end
61
- alias_method :search_results, :paginate_found
62
-
63
- # Make searchlogic query from simple query option
64
- # Needed to be reimplemented in subclasses
65
- #
66
- # @param [String] simple query string
67
- # @return [Hash] searchlogic query
68
- def parse_simple_query(query)
69
- {:"#{name_field}_like" => query}
17
+ # Make a slug from object‘s #name_field
18
+ # @param [ActiveRecord::Base] model object, which slug is making
19
+ # @return [String] slug made from models #name_field
20
+ def make_slug(model)
21
+ model.send(name_field).parameterize
70
22
  end
23
+ end
71
24
 
72
- # Make a slug from object’s NameField
73
- # @param [ActiveRecord::Base] object, which slug is making
74
- # @return [String] slug
75
- def make_slug(object)
76
- object.send(name_field).parameterize
25
+ module InstanceMethods
26
+ # String representation of model, based on Model’s #name_field
27
+ def to_s
28
+ send(self.class.name_field)
77
29
  end
78
30
  end
79
31
  end
80
32
  end
33
+
34
+ if defined?(InheritedResources)
35
+ require 'espresso/model/inherited_resources'
36
+ end
@@ -0,0 +1,20 @@
1
+ require 'espresso/model'
2
+ require 'espresso/collection'
3
+
4
+ module Espresso
5
+ module Model
6
+ included do
7
+ named_scope :for_collection, :conditions => '1 = 1'
8
+ named_scope :for_feed, :order => 'created_at DESC'
9
+ end
10
+
11
+ module ClassMethods
12
+ # Collection of resources, found by params
13
+ # @param [Hash] options options for ActiveRecord::Base#find
14
+ # @return [Espresso::Collection, Array] collection of resources
15
+ def collection(options = {})
16
+ Espresso::Collection.new(self.for_collection, options)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,261 @@
1
+ require 'espresso'
2
+ require 'active_support/core_ext/module'
3
+
4
+ module Espresso
5
+ module View
6
+ extend Espresso::Concern
7
+
8
+ autoload :FormBuilder, 'espresso/view/form_builder'
9
+
10
+ mattr_accessor :block_prefix
11
+ self.block_prefix = 'b'
12
+
13
+ # Generic espresso block classes
14
+ # @param [String, Symbol] main_class main block class
15
+ # @param [Array] modifiers array of modifiers for main block class
16
+ # @param [Hash] options another options
17
+ # @option options [String] :type (Espresso::View.block_prefix) type of the block
18
+ def self.block_classes(main_class, modifiers = [], options = {})
19
+ options ||= {}
20
+ options[:type] ||= Espresso::View.block_prefix
21
+
22
+ main_class = "#{options[:type]}-#{main_class}"
23
+ [main_class].tap do |classes|
24
+ modifiers.each do |modifier|
25
+ classes << "#{main_class}_#{modifier}"
26
+ end
27
+ end.join(' ')
28
+ end
29
+
30
+ module ClassMethods
31
+ end
32
+
33
+ module InstanceMethods
34
+ VIEW_PLACEHOLDERS = {
35
+ 'create' => 'new',
36
+ 'update' => 'edit'
37
+ }
38
+
39
+ # Overwrites current url.
40
+ # By default uses full path (with host), if it is not overwrited in options
41
+ # @param [Hash] overwrites hash of params to overwrite
42
+ # @param [Hash] options hash of options to url_for
43
+ # @return [String] overwrited url
44
+ def overwrite_url(overwrites, options = {})
45
+ overwrites ||= {}
46
+ options ||= {}
47
+ options[:only_path] = false unless options.key?(:only_path)
48
+ url_for({:overwrite_params => (overwrites || {})}.merge(options))
49
+ end
50
+
51
+ # Overwrites current path.
52
+ # By default uses relative path (started with /), if it is not overwrited in options
53
+ # @param [Hash] overwrites hash of params to overwrite
54
+ # @param [Hash] options hash of options to url_for
55
+ # @return [String] overwrited path
56
+ def overwrite_path(overwrites, options = {})
57
+ options ||= {}
58
+ options[:only_path] = true unless options.key?(:only_path)
59
+ overwrite_url(overwrites, options)
60
+ end
61
+
62
+ # Helper to write time in human- and machine-readable format
63
+ # @param [Time, DateTime] time time to represent
64
+ # @return [String] <time> tag with time representation
65
+ def time(time, options = {})
66
+ format = options.delete(:format) { :long }
67
+ content_tag(:time,
68
+ l(time, :format => format),
69
+ options.merge(:time => time.xmlschema))
70
+ end
71
+
72
+ # Helper to write date in human- and machine-readable format
73
+ # @param [Time, DateTime, Date] time_or_date time or date to represent
74
+ # @return [String] <time> tag with time or date to represent
75
+ def date(time_or_date, options = {})
76
+ time(time_or_date.to_date, options)
77
+ end
78
+
79
+
80
+
81
+ # Model‘s classes, based on Model.model_modifiers
82
+ # @param [ActiveRecord::Base] model model to build classes from
83
+ def model_classes(model)
84
+ klass = model.class
85
+ main_class = klass.name.underscore.gsub(/(_|\/)/, '-')
86
+ modifiers = if klass.respond_to?(:model_modifiers)
87
+ klass.model_modifiers.find_all do |modifier|
88
+ method = "#{modifier}?"
89
+ model.respond_to?(method) && model.send(method)
90
+ end
91
+ else
92
+ []
93
+ end
94
+ Espresso::View.block_classes(main_class,
95
+ modifiers)
96
+ end
97
+
98
+ # Finds apropriate view name
99
+ # @return [String] current view name
100
+ def view_name
101
+ unless @view_name
102
+ action_name = controller.action_name
103
+ @view_name = VIEW_PLACEHOLDERS[action_name] || action_name
104
+ end
105
+ @view_name
106
+ end
107
+
108
+ # Makes default page title, based on controller and action
109
+ # @return [String] default page title
110
+ def default_page_title
111
+ text = case view_name
112
+ when 'index'
113
+ if collection?
114
+ resource_class.name
115
+ else
116
+ controller_name.camelize
117
+ end
118
+ when 'new'
119
+ "#{t('espresso.navigation.new', :default => 'New')} #{(resource? ? resource_class : controller_name.classify.constantize).human_name}"
120
+ when 'edit'
121
+ "#{t('espresso.navigation.edit', :default => 'Edit')} #{(resource? ? resource_class : controller_name.classify.constantize).human_name}"
122
+ else
123
+ t("navigation.#{controller_name}.#{view_name}")
124
+ end
125
+ %(<span class="translation_missing">#{text}</span>)
126
+ end
127
+
128
+ def page_title(title = nil, strip = false)
129
+ @page_title = if title
130
+ title
131
+ elsif @page_title
132
+ @page_title
133
+ else
134
+ default = if !Rails.env.development?
135
+ default_page_title
136
+ else
137
+ nil
138
+ end
139
+
140
+ rsrc = if resource?
141
+ if resource.new_record?
142
+ resource_class.human_name
143
+ else
144
+ link_to(resource, resource_path)
145
+ end
146
+ else
147
+ nil
148
+ end
149
+
150
+ t("navigation.#{controller_name}.#{view_name}",
151
+ :default => default,
152
+ :resource => rsrc
153
+ )
154
+ end
155
+ if strip
156
+ strip_tags(@page_title)
157
+ else
158
+ @page_title
159
+ end
160
+ end
161
+
162
+ def head_title(default = false, separator = ' | ')
163
+ default ||= t('application.meta.title')
164
+ [page_title(nil, true), default].compact.join(separator)
165
+ end
166
+
167
+ # Draws navigation list, using <li> with <a>
168
+ # @param [Array<Symbol, String>] menu list of menu items (paths without /)
169
+ # @return [String] Resulting menu without <ul> or <ol>
170
+ def navigation_list(menu)
171
+ ''.tap do |result|
172
+ menu.each do |item|
173
+ path = "/#{item}"
174
+ uri = request.request_uri
175
+ title = t("navigation.#{item}.index", :default => item.to_s.camelize)
176
+ result << content_tag(:li, :class => uri.starts_with?(path) ? 'selected' : nil) do
177
+ link_to_unless_current(title, path) {
178
+ content_tag(:strong, title)
179
+ }
180
+ end
181
+ end
182
+ end
183
+ end
184
+
185
+ # Set online statistics trackers
186
+ # @param [Hash] options online statistics keys
187
+ # @option options [Hash] :piwik Piwik code: id. site
188
+ # @option options [String, Numeric] :metrika Yandex.Metrika code
189
+ # @option options [String] :analytics,
190
+ def online_stats(options = {})
191
+ static_includes = []
192
+ dynamic_includes = ''
193
+ noscript_includes = []
194
+ initializers = []
195
+
196
+ if piwik = options.delete(:piwik)
197
+ static_includes << "//#{piwik[:site]}/piwik.js"
198
+ initializers << "var piwikTracker=Piwik.getTracker('//#{piwik[:site]}/piwik.php',#{piwik[:id]});piwikTracker.trackPageView();piwikTracker.enableLinkTracking();"
199
+ noscript_includes << "//#{piwik[:site]}/piwik.php?idsite=#{piwik[:id]}"
200
+ end
201
+
202
+ if metrika = options.delete(:metrika)
203
+ static_includes << '//mc.yandex.ru/resource/watch.js'
204
+ initializers << "var yaCounter#{metrika}=new Ya.Metrika(#{metrika});"
205
+ noscript_includes << "//mc.yandex.ru/watch/#{metrika}"
206
+ end
207
+
208
+ if analytics = options.delete(:analytics)
209
+ dynamic_includes << 'var gaJsHost=("https:"==document.location.protocol)?"https://ssl.":"http://www.";'
210
+ dynamic_includes << 'document.write(unescape("%3Cscript src=\'"+gaJsHost+"google-analytics.com/ga.js\' type=\'text/javascript\'%3E%3C/script%3Ei"));'
211
+ initializers << "var pageTracker=_gat._getTracker('#{analytics}');pageTracker._trackPageview();"
212
+ end
213
+
214
+ ''.tap do |result|
215
+ unless dynamic_includes.empty?
216
+ result << javascript_tag(dynamic_includes)
217
+ end
218
+ result << javascript_include_tag(static_includes) unless static_includes.empty?
219
+ unless initializers.empty?
220
+ initializers = initializers.collect do |initializer|
221
+ "try {#{initializer}} catch(e) {}"
222
+ end.join("\n")
223
+ result << javascript_tag(initializers)
224
+ end
225
+
226
+ unless noscript_includes.empty?
227
+ includes = noscript_includes.collect do |noscript|
228
+ %(<img src="#{noscript}" style="border:0" alt="" />)
229
+ end.join("\n")
230
+ result << content_tag(:noscript,
231
+ content_tag(:div,
232
+ includes,
233
+ :style => 'position: absolute'))
234
+ end
235
+ end
236
+ end
237
+
238
+ # Make body’s modifiers, based on controller_name and action_name
239
+ def body_modifiers
240
+ {:class => "m-#{controller_name} m-#{controller_name}_#{action_name}"}
241
+ end
242
+
243
+ end
244
+ end
245
+ end
246
+
247
+ if defined?(WillPaginate)
248
+ require 'espresso/view/will_paginate'
249
+ end
250
+
251
+ if defined?(InheritedResources)
252
+ require 'espresso/view/inherited_resources'
253
+ end
254
+
255
+ if defined?(HasScope)
256
+ require 'espresso/view/has_scope'
257
+ end
258
+
259
+ if defined?(Searchlogic)
260
+ require 'espresso/view/form_builder'
261
+ end