espresso 0.1.1 → 0.1.12
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/README.rdoc +1 -1
- data/Rakefile +11 -7
- data/VERSION +1 -1
- data/espresso.gemspec +28 -16
- data/init.rb +1 -4
- data/lib/espresso/action_controller.rb +7 -0
- data/lib/espresso/action_view/form_builder.rb +58 -0
- data/lib/espresso/action_view/navigation.rb +100 -0
- data/lib/espresso/action_view/resources.rb +59 -0
- data/lib/espresso/action_view/scopes.rb +38 -0
- data/lib/espresso/action_view/stats.rb +54 -0
- data/lib/espresso/action_view.rb +21 -0
- data/lib/espresso/haml.rb +26 -0
- data/lib/espresso/locales/ru.yml +5 -0
- data/lib/espresso/model.rb +36 -21
- data/lib/espresso/resources.rb +79 -0
- data/lib/espresso/resources_helpers.rb +24 -0
- data/lib/espresso.rb +24 -6
- metadata +73 -30
- data/lib/espresso/helpers.rb +0 -34
- data/lib/espresso/objects_controller.rb +0 -42
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -10,7 +10,7 @@ Description goes here.
|
|
10
10
|
future version unintentionally.
|
11
11
|
* Commit, do not mess with rakefile, version, or history.
|
12
12
|
(if you want to have your own version, that is fine but
|
13
|
-
|
13
|
+
bump version in a commit by itself I can ignore when I pull)
|
14
14
|
* Send me a pull request. Bonus points for topic branches.
|
15
15
|
|
16
16
|
== Copyright
|
data/Rakefile
CHANGED
@@ -4,16 +4,17 @@ require 'rake'
|
|
4
4
|
begin
|
5
5
|
require 'jeweler'
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
|
-
gem.name =
|
7
|
+
gem.name = 'espresso'
|
8
8
|
gem.summary = %Q{Rails extender to simplify rails development}
|
9
9
|
gem.description = %Q{Useful templates for controller and model functions}
|
10
|
-
gem.email =
|
11
|
-
gem.homepage =
|
12
|
-
gem.authors = [
|
13
|
-
gem.add_development_dependency "thoughtbot-shoulda"
|
10
|
+
gem.email = 'rotuka@tokak.ru'
|
11
|
+
gem.homepage = 'http://github.com/krasivotokak/espresso'
|
12
|
+
gem.authors = ['Alexander Semyonov']
|
14
13
|
gem.add_dependency('searchlogic', '>= 2.2.3')
|
15
|
-
gem.add_dependency('
|
16
|
-
gem.add_dependency('
|
14
|
+
gem.add_dependency('inherited_resources', '>= 0.8.5')
|
15
|
+
gem.add_dependency('will_paginate', '>= 2.3.11')
|
16
|
+
gem.add_dependency('formtastic', '>= 0.9.7')
|
17
|
+
gem.add_development_dependency('shoulda')
|
17
18
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
18
19
|
end
|
19
20
|
Jeweler::GemcutterTasks.new
|
@@ -54,5 +55,8 @@ rescue LoadError
|
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
58
|
+
desc 'Generate documentation'
|
59
|
+
task :doc => :yard
|
60
|
+
|
57
61
|
desc "Bump patch version and release to github and gemcutter"
|
58
62
|
task :bump => %w(version:bump:patch release gemcutter:release install)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.12
|
data/espresso.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{espresso}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.12"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alexander Semyonov"]
|
12
|
-
s.date = %q{
|
12
|
+
s.date = %q{2010-03-25}
|
13
13
|
s.description = %q{Useful templates for controller and model functions}
|
14
14
|
s.email = %q{rotuka@tokak.ru}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,18 +25,26 @@ Gem::Specification.new do |s|
|
|
25
25
|
"espresso.gemspec",
|
26
26
|
"init.rb",
|
27
27
|
"lib/espresso.rb",
|
28
|
-
"lib/espresso/
|
28
|
+
"lib/espresso/action_controller.rb",
|
29
|
+
"lib/espresso/action_view.rb",
|
30
|
+
"lib/espresso/action_view/form_builder.rb",
|
31
|
+
"lib/espresso/action_view/navigation.rb",
|
32
|
+
"lib/espresso/action_view/resources.rb",
|
33
|
+
"lib/espresso/action_view/scopes.rb",
|
34
|
+
"lib/espresso/action_view/stats.rb",
|
35
|
+
"lib/espresso/haml.rb",
|
29
36
|
"lib/espresso/locales/en.yml",
|
30
37
|
"lib/espresso/locales/ru.yml",
|
31
38
|
"lib/espresso/model.rb",
|
32
|
-
"lib/espresso/
|
39
|
+
"lib/espresso/resources.rb",
|
40
|
+
"lib/espresso/resources_helpers.rb",
|
33
41
|
"test/espresso_test.rb",
|
34
42
|
"test/test_helper.rb"
|
35
43
|
]
|
36
44
|
s.homepage = %q{http://github.com/krasivotokak/espresso}
|
37
45
|
s.rdoc_options = ["--charset=UTF-8"]
|
38
46
|
s.require_paths = ["lib"]
|
39
|
-
s.rubygems_version = %q{1.3.
|
47
|
+
s.rubygems_version = %q{1.3.6}
|
40
48
|
s.summary = %q{Rails extender to simplify rails development}
|
41
49
|
s.test_files = [
|
42
50
|
"test/espresso_test.rb",
|
@@ -48,20 +56,24 @@ Gem::Specification.new do |s|
|
|
48
56
|
s.specification_version = 3
|
49
57
|
|
50
58
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
51
|
-
s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
52
59
|
s.add_runtime_dependency(%q<searchlogic>, [">= 2.2.3"])
|
53
|
-
s.add_runtime_dependency(%q<
|
54
|
-
s.add_runtime_dependency(%q<
|
60
|
+
s.add_runtime_dependency(%q<inherited_resources>, [">= 0.8.5"])
|
61
|
+
s.add_runtime_dependency(%q<will_paginate>, [">= 2.3.11"])
|
62
|
+
s.add_runtime_dependency(%q<formtastic>, [">= 0.9.7"])
|
63
|
+
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
55
64
|
else
|
56
|
-
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
57
65
|
s.add_dependency(%q<searchlogic>, [">= 2.2.3"])
|
58
|
-
s.add_dependency(%q<
|
59
|
-
s.add_dependency(%q<
|
66
|
+
s.add_dependency(%q<inherited_resources>, [">= 0.8.5"])
|
67
|
+
s.add_dependency(%q<will_paginate>, [">= 2.3.11"])
|
68
|
+
s.add_dependency(%q<formtastic>, [">= 0.9.7"])
|
69
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
60
70
|
end
|
61
71
|
else
|
62
|
-
s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
|
63
72
|
s.add_dependency(%q<searchlogic>, [">= 2.2.3"])
|
64
|
-
s.add_dependency(%q<
|
65
|
-
s.add_dependency(%q<
|
73
|
+
s.add_dependency(%q<inherited_resources>, [">= 0.8.5"])
|
74
|
+
s.add_dependency(%q<will_paginate>, [">= 2.3.11"])
|
75
|
+
s.add_dependency(%q<formtastic>, [">= 0.9.7"])
|
76
|
+
s.add_dependency(%q<shoulda>, [">= 0"])
|
66
77
|
end
|
67
78
|
end
|
79
|
+
|
data/init.rb
CHANGED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'formtastic'
|
2
|
+
|
3
|
+
module Espresso
|
4
|
+
module ActionView
|
5
|
+
class FormBuilder < Formtastic::SemanticFormBuilder
|
6
|
+
def submit(value=nil, options={})
|
7
|
+
value, options = nil, value if value.is_a?(Hash)
|
8
|
+
value ||= submit_default_value
|
9
|
+
@template.submit_tag(value, options.reverse_merge(:id => "#{object_name}_submit"))
|
10
|
+
end
|
11
|
+
|
12
|
+
def inline_errors_for(method, options = nil) #:nodoc:
|
13
|
+
if render_inline_errors?
|
14
|
+
errors = Array(@object.errors[method.to_sym]) +
|
15
|
+
Array(@object.errors[:"#{method}_id"])
|
16
|
+
send(:"error_#{@@inline_errors}", [*errors]) if errors.present?
|
17
|
+
else
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def submit_default_value
|
23
|
+
model = if object.class.respond_to?(:model_name)
|
24
|
+
object.class.human_name
|
25
|
+
else
|
26
|
+
@object_name.to_s.humanize
|
27
|
+
end
|
28
|
+
|
29
|
+
defaults = []
|
30
|
+
defaults << :"helpers.submit.#{object_name}.#{form_action}"
|
31
|
+
defaults << :"helpers.submit.#{form_action}"
|
32
|
+
defaults << "#{form_action.to_s.humanize} #{model}"
|
33
|
+
|
34
|
+
I18n.t(defaults.shift, :model => model, :default => defaults)
|
35
|
+
end
|
36
|
+
|
37
|
+
def commit_button(*args)
|
38
|
+
options = args.extract_options!
|
39
|
+
|
40
|
+
button_html = options.delete(:button_html) || {}
|
41
|
+
button_html.merge!(:class => [button_html[:class], form_action].compact.join(' '))
|
42
|
+
element_class = ['commit', options.delete(:class)].compact.join(' ')
|
43
|
+
accesskey = (options.delete(:accesskey) || @@default_commit_button_accesskey) unless button_html.has_key?(:accesskey)
|
44
|
+
button_html = button_html.merge(:accesskey => accesskey) if accesskey
|
45
|
+
template.content_tag(:li, self.submit(options.delete(:label), button_html), :class => element_class)
|
46
|
+
end
|
47
|
+
|
48
|
+
protected
|
49
|
+
def model_object
|
50
|
+
@object.respond_to?(:to_model) ? @object.to_model : @object
|
51
|
+
end
|
52
|
+
|
53
|
+
def form_action
|
54
|
+
model_object ? (model_object.new_record? ? :create : :update) : :submit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'will_paginate/view_helpers'
|
2
|
+
|
3
|
+
module Espresso
|
4
|
+
module ActionView
|
5
|
+
module Navigation
|
6
|
+
VIEW_PLACEHOLDERS = {
|
7
|
+
'create' => 'new',
|
8
|
+
'update' => 'edit'
|
9
|
+
}
|
10
|
+
|
11
|
+
# Finds apropriate view name
|
12
|
+
def view_name
|
13
|
+
unless @view_name
|
14
|
+
action_name = controller.action_name
|
15
|
+
@view_name = VIEW_PLACEHOLDERS[action_name] || action_name
|
16
|
+
end
|
17
|
+
@view_name
|
18
|
+
end
|
19
|
+
|
20
|
+
# Make default page title, based on controller and action
|
21
|
+
def default_page_title
|
22
|
+
text = case view_name
|
23
|
+
when 'index'
|
24
|
+
controller_name.camelize
|
25
|
+
when 'new'
|
26
|
+
"#{t('espresso.navigation.new', :default => 'New')} #{controller_name.classify.constantize.human_name}"
|
27
|
+
when 'edit'
|
28
|
+
"#{t('espresso.navigation.edit', :default => 'Editing')} #{controller_name.classify.constantize.human_name}"
|
29
|
+
else
|
30
|
+
t("navigation.#{controller_name}.#{view_name}")
|
31
|
+
end
|
32
|
+
%(<span class="translation_missing">#{text}</span>)
|
33
|
+
end
|
34
|
+
|
35
|
+
def page_title(title = nil, strip = false)
|
36
|
+
@page_title = if title
|
37
|
+
title
|
38
|
+
elsif @page_title
|
39
|
+
@page_title
|
40
|
+
else
|
41
|
+
default = if Rails.env.production?
|
42
|
+
default_page_title
|
43
|
+
else
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
rsrc = if resource?
|
48
|
+
if resource.new_record?
|
49
|
+
resource_class.human_name
|
50
|
+
else
|
51
|
+
link_to(resource, resource_path)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
|
57
|
+
t("navigation.#{controller_name}.#{view_name}",
|
58
|
+
:default => default,
|
59
|
+
:resource => rsrc
|
60
|
+
)
|
61
|
+
end
|
62
|
+
if strip
|
63
|
+
strip_tags(@page_title)
|
64
|
+
else
|
65
|
+
@page_title
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def head_title(default = false, separator = ' | ')
|
70
|
+
default ||= t('application.meta.title')
|
71
|
+
strip_tags([page_title, default].compact.join(separator))
|
72
|
+
end
|
73
|
+
|
74
|
+
def navigation_list(menu)
|
75
|
+
returning '' do |result|
|
76
|
+
menu.each do |item|
|
77
|
+
path = "/#{item}"
|
78
|
+
uri = request.request_uri
|
79
|
+
title = t("navigation.#{item}.index", :default => item.to_s.camelize)
|
80
|
+
result << content_tag(:li, :class => uri.starts_with?(path) ? 'selected' : nil) do
|
81
|
+
link_to_unless_current(title, path) {
|
82
|
+
content_tag(:strong, title)
|
83
|
+
}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
include WillPaginate::ViewHelpers
|
90
|
+
def will_paginate_with_i18n(collection, options = {})
|
91
|
+
will_paginate_without_i18n(collection,
|
92
|
+
options.merge({
|
93
|
+
:class => 'b-pagination',
|
94
|
+
:previous_label => t('espresso.navigation.previous', :default => '← Previous'),
|
95
|
+
:next_label => t('espresso.navigation.next', :default => 'Next →')}))
|
96
|
+
end
|
97
|
+
alias_method_chain :will_paginate, :i18n
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Espresso
|
2
|
+
module ActionView
|
3
|
+
module Resources
|
4
|
+
def link_to_new(klass=nil, path=nil)
|
5
|
+
klass ||= resource_class
|
6
|
+
klass_underscored = klass.name.underscore
|
7
|
+
path ||= if klass == resource_class
|
8
|
+
new_resource_path
|
9
|
+
else
|
10
|
+
[:new, klass_underscored]
|
11
|
+
end
|
12
|
+
link_to(t("helpers.action.#{klass_underscored}.new",
|
13
|
+
:default => [:'helpers.action.new', 'Добавить']),
|
14
|
+
path,
|
15
|
+
:class => 'b-action b-action_new')
|
16
|
+
rescue
|
17
|
+
end
|
18
|
+
|
19
|
+
def link_to_show(object=nil)
|
20
|
+
object ||= resource
|
21
|
+
link_to(t("helpers.action.#{object.class.name.underscore}.show",
|
22
|
+
:default => [:'helpers.action.show', object.to_s]),
|
23
|
+
object,
|
24
|
+
:class => 'b-action b-action_show')
|
25
|
+
rescue
|
26
|
+
end
|
27
|
+
|
28
|
+
def link_to_edit(object=nil, path=nil)
|
29
|
+
object ||= resource
|
30
|
+
path ||= object == resource ? edit_resource_path : [:edit, object]
|
31
|
+
link_to(t("helpers.action.#{object.class.name.underscore}.edit",
|
32
|
+
:default => [:'helpers.action.edit', 'Редактировать']),
|
33
|
+
path,
|
34
|
+
:class => 'b-action b-action_edit')
|
35
|
+
rescue
|
36
|
+
end
|
37
|
+
|
38
|
+
def link_to_destroy(object=nil, path=nil)
|
39
|
+
object ||= resource
|
40
|
+
path ||= object == resource ? resource_path : object
|
41
|
+
link_to(t("helpers.action.#{object.class.name.underscore}.edit",
|
42
|
+
:default => [:'helpers.action.destroy', 'Удалить']),
|
43
|
+
path,
|
44
|
+
:class => 'b-action b-action_destroy',
|
45
|
+
:method => :delete,
|
46
|
+
:confirm => 'Вы уверены?')
|
47
|
+
end
|
48
|
+
|
49
|
+
def link_to_index
|
50
|
+
link_to(t("helpers.action.#{controller_name.singularize}.index",
|
51
|
+
:default => [:'helpers.action.index', '← К списку']),
|
52
|
+
collection_path,
|
53
|
+
:class => 'b-action b-action_index'
|
54
|
+
)
|
55
|
+
rescue
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Espresso
|
2
|
+
module ActionView
|
3
|
+
module Scopes
|
4
|
+
def simple_search
|
5
|
+
returning '' do |form|
|
6
|
+
form << form_tag(url_for(:action => :index), :method => :get)
|
7
|
+
form << content_tag(:table, :class => 'b-search') do
|
8
|
+
content_tag(:tr) do
|
9
|
+
returning '' do |result|
|
10
|
+
result << content_tag(:td,
|
11
|
+
content_tag(:div, text_field_tag(:q, params[:q], :type => 'search'), :class => 'b-input'),
|
12
|
+
:class => 'input')
|
13
|
+
result << content_tag(:td,
|
14
|
+
submit_tag(t('krasivotokak.espresso.find', :default => 'Find!'), :class => 'submit'),
|
15
|
+
:class => 'button')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
form << yield if block_given?
|
20
|
+
form << '</form>'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def scope_filter(scopes)
|
25
|
+
items = scopes.inject([]) do |list, scope|
|
26
|
+
list << link_to_unless_current(t(".#{scope}"), collection_path(scope => true))
|
27
|
+
list
|
28
|
+
end
|
29
|
+
|
30
|
+
content_tag(:div, :class => 'b-scope-filter') do
|
31
|
+
content_tag(:ul, :class => 'b-hlist b-hlist_vline') do
|
32
|
+
"<li>#{items.join('<li></li>')}</li>"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Espresso
|
2
|
+
module ActionView
|
3
|
+
module Stats
|
4
|
+
# Set online statistics trackers
|
5
|
+
# @options
|
6
|
+
def online_stats(options = {})
|
7
|
+
static_includes = []
|
8
|
+
dynamic_includes = ''
|
9
|
+
noscript_includes = []
|
10
|
+
initializers = []
|
11
|
+
|
12
|
+
if piwik = options.delete(:piwik)
|
13
|
+
static_includes << "//#{piwik[:site]}/piwik.js"
|
14
|
+
initializers << "var piwikTracker=Piwik.getTracker('//#{piwik[:site]}/piwik.php',#{piwik[:id]});piwikTracker.trackPageView();piwikTracker.enableLinkTracking();"
|
15
|
+
noscript_includes << "//#{piwik[:site]}/piwik.php?idsite=#{piwik[:id]}"
|
16
|
+
end
|
17
|
+
|
18
|
+
if metrika = options.delete(:metrika)
|
19
|
+
static_includes << '//mc.yandex.ru/resource/watch.js'
|
20
|
+
initializers << "var yaCounter#{metrika}=new Ya.Metrika(#{metrika});"
|
21
|
+
noscript_includes << "//mc.yandex.ru/watch/#{metrika}"
|
22
|
+
end
|
23
|
+
|
24
|
+
if analytics = options.delete(:analytics)
|
25
|
+
dynamic_includes << 'var gaJsHost=("https:"==document.location.protocol)?"https://ssl.":"http://www.";'
|
26
|
+
dynamic_includes << 'document.write(unescape("%3Cscript src=\'"+gaJsHost+"google-analytics.com/ga.js\' type=\'text/javascript\'%3E%3C/script%3Ei"));'
|
27
|
+
initializers << "var pageTracker=_gat._getTracker('#{analytics}');pageTracker._trackPageview();"
|
28
|
+
end
|
29
|
+
|
30
|
+
returning('') do |result|
|
31
|
+
unless dynamic_includes.empty?
|
32
|
+
result << javascript_tag(dynamic_includes)
|
33
|
+
end
|
34
|
+
result << javascript_include_tag(static_includes) unless static_includes.empty?
|
35
|
+
unless initializers.empty?
|
36
|
+
initializers = initializers.collect do |initializer|
|
37
|
+
"try {#{initializer}} catch(e) {}"
|
38
|
+
end.join("\n")
|
39
|
+
result << javascript_tag(initializers)
|
40
|
+
end
|
41
|
+
unless noscript_includes.empty?
|
42
|
+
includes = noscript_includes.collect do |noscript|
|
43
|
+
%(<img src="#{noscript}" style="border:0" alt="" />)
|
44
|
+
end.join("\n")
|
45
|
+
result << content_tag(:noscript,
|
46
|
+
content_tag(:div,
|
47
|
+
includes,
|
48
|
+
:style => 'position: absolute'))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Espresso
|
2
|
+
module ActionView
|
3
|
+
autoload :Resources, 'espresso/action_view/resources'
|
4
|
+
autoload :Scopes, 'espresso/action_view/scopes'
|
5
|
+
autoload :Navigation, 'espresso/action_view/navigation'
|
6
|
+
autoload :FormBuilder, 'espresso/action_view/form_builder'
|
7
|
+
autoload :Stats, 'espresso/action_view/stats'
|
8
|
+
|
9
|
+
include Resources
|
10
|
+
include Scopes
|
11
|
+
include Navigation
|
12
|
+
include Stats
|
13
|
+
|
14
|
+
# Make body’s modifiers, based on controller_name and action_name
|
15
|
+
def body_modifiers
|
16
|
+
{:class => "m-#{controller_name} m-#{controller_name}_#{action_name}"}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Formtastic::SemanticFormHelper.builder = Espresso::ActionView::FormBuilder
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'haml'
|
2
|
+
require 'haml/buffer'
|
3
|
+
|
4
|
+
class Haml::Buffer
|
5
|
+
# Takes an array of objects and uses the class and id of the first
|
6
|
+
# one to create an attributes hash.
|
7
|
+
# The second object, if present, is used as a prefix,
|
8
|
+
# just like you can do with `dom_id()` and `dom_class()` in Rails
|
9
|
+
def parse_object_ref(ref)
|
10
|
+
prefix = ref[1]
|
11
|
+
ref = ref[0]
|
12
|
+
# Let's make sure the value isn't nil. If it is, return the default Hash.
|
13
|
+
return {} if ref.nil?
|
14
|
+
class_name = underscore(ref.class)
|
15
|
+
id = "#{class_name}_#{ref.id || 'new'}"
|
16
|
+
|
17
|
+
if ref.respond_to?(:model_class)
|
18
|
+
class_name = ref.model_class
|
19
|
+
elsif prefix
|
20
|
+
class_name = "#{prefix}_#{class_name}"
|
21
|
+
id = "#{prefix}_#{id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
{'id' => id, 'class' => class_name}
|
25
|
+
end
|
26
|
+
end
|
data/lib/espresso/locales/ru.yml
CHANGED
data/lib/espresso/model.rb
CHANGED
@@ -1,17 +1,47 @@
|
|
1
1
|
require 'searchlogic'
|
2
|
+
require 'will_paginate'
|
2
3
|
|
3
4
|
module Espresso
|
4
5
|
# @author Alexander Semyonov
|
5
6
|
module Model
|
6
|
-
unloadable
|
7
|
-
|
8
7
|
def self.included(model)
|
8
|
+
super
|
9
9
|
model.class_eval do
|
10
10
|
extend ClassMethods
|
11
|
-
|
11
|
+
|
12
|
+
class_inheritable_accessor :model_attrs, :name_field, :per_page
|
13
|
+
|
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
|
+
}
|
12
24
|
end
|
13
25
|
end
|
14
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(' ')
|
43
|
+
end
|
44
|
+
|
15
45
|
module ClassMethods
|
16
46
|
# Paginates search results
|
17
47
|
#
|
@@ -24,9 +54,9 @@ module Espresso
|
|
24
54
|
def paginate_found(page = nil, query = {}, simple_query = nil)
|
25
55
|
query ||= {}
|
26
56
|
query.merge!(self.parse_simple_query(simple_query)) if simple_query
|
27
|
-
|
28
|
-
|
29
|
-
[
|
57
|
+
searchlogic = search(query)
|
58
|
+
results = searchlogic.paginate(:page => page)
|
59
|
+
[searchlogic, results]
|
30
60
|
end
|
31
61
|
alias_method :search_results, :paginate_found
|
32
62
|
|
@@ -39,13 +69,6 @@ module Espresso
|
|
39
69
|
{:"#{name_field}_like" => query}
|
40
70
|
end
|
41
71
|
|
42
|
-
# «NameField» is a main field, used to represent model in to_s method and in simple queries
|
43
|
-
# @param [Symbol, String] new_name_field new field name
|
44
|
-
# @return [Symbol] field name
|
45
|
-
def name_field
|
46
|
-
:name
|
47
|
-
end
|
48
|
-
|
49
72
|
# Make a slug from object’s NameField
|
50
73
|
# @param [ActiveRecord::Base] object, which slug is making
|
51
74
|
# @return [String] slug
|
@@ -53,13 +76,5 @@ module Espresso
|
|
53
76
|
object.send(name_field).parameterize
|
54
77
|
end
|
55
78
|
end
|
56
|
-
|
57
|
-
module InstanceMethods
|
58
|
-
def to_s
|
59
|
-
send(self.class.name_field).to_s
|
60
|
-
end
|
61
|
-
|
62
|
-
protected
|
63
|
-
end
|
64
79
|
end
|
65
80
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'inherited_resources'
|
2
|
+
require 'has_scope'
|
3
|
+
|
4
|
+
module Espresso
|
5
|
+
module Resources
|
6
|
+
def self.resources(controller = nil)
|
7
|
+
controller ||= self
|
8
|
+
controller.inherit_resources
|
9
|
+
controller.extend ClassMethods
|
10
|
+
controller.send(:include, InstanceMethods)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(controller)
|
14
|
+
resources(controller)
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
# Adds ability to build feeds for resource’s collections.
|
19
|
+
# By default adds Atom feed
|
20
|
+
# @example Add Atom feed for #index
|
21
|
+
# has_feed :atom
|
22
|
+
# @example Add Atom and RSS feed for #index
|
23
|
+
# has_feed :atom, :rss
|
24
|
+
# @example Add Atom, Rss, and ITunes feed for #index, #list and #archive
|
25
|
+
# has_feed :atom, :rss, :itunes_feed, :only => [:index, :list, :archive]
|
26
|
+
def has_feed(*args)
|
27
|
+
options = args.extract_options!
|
28
|
+
if options.empty?
|
29
|
+
options[:only] = :index
|
30
|
+
end
|
31
|
+
|
32
|
+
class_inheritable_accessor(:feed_formats) unless respond_to?(:feed_formats)
|
33
|
+
self.feed_formats = args.empty? ? [:atom] : args
|
34
|
+
self.feed_formats = self.feed_formats.map(&:to_sym)
|
35
|
+
|
36
|
+
self.feed_formats.each do |format|
|
37
|
+
respond_to format, options
|
38
|
+
end
|
39
|
+
|
40
|
+
include FeedScope
|
41
|
+
has_scope :for_feed, options.merge(:default => true,
|
42
|
+
:type => :boolean,
|
43
|
+
:if => :feed_scope_applicable?)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
module FeedScope
|
48
|
+
def feed_scope_applicable?
|
49
|
+
params[:format] && self.class.feed_formats.include?(params[:format].to_sym)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module InstanceMethods
|
54
|
+
protected
|
55
|
+
|
56
|
+
# Find collection of objects with pagination.
|
57
|
+
# Also made Searchlogic object @search
|
58
|
+
#
|
59
|
+
# @return [WillPaginate::Collection] collection of objects
|
60
|
+
def collection
|
61
|
+
unless (result = get_collection_ivar).present?
|
62
|
+
@search, result = end_of_association_chain.for_index.
|
63
|
+
search_results(params[:page],
|
64
|
+
params[:query],
|
65
|
+
params[:q])
|
66
|
+
set_collection_ivar(result)
|
67
|
+
end
|
68
|
+
result
|
69
|
+
end
|
70
|
+
|
71
|
+
# Build interpolation options for flash messages
|
72
|
+
def interpolation_options
|
73
|
+
if resource?
|
74
|
+
{ :resource_title => resource.to_s }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Espresso
|
2
|
+
module ResourcesHelpers
|
3
|
+
def self.included(base)
|
4
|
+
super
|
5
|
+
base.send(:helper_method, :resource?, :collection?)
|
6
|
+
end
|
7
|
+
|
8
|
+
# Does the action or view have a resource
|
9
|
+
# @return [Boolean] having a resource
|
10
|
+
def resource?
|
11
|
+
resource
|
12
|
+
rescue
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
# Does the action or view have a collection of objects
|
17
|
+
# @return [Boolean] having a collection
|
18
|
+
def collection?
|
19
|
+
collection
|
20
|
+
rescue
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/espresso.rb
CHANGED
@@ -1,14 +1,32 @@
|
|
1
1
|
module Espresso
|
2
|
+
MODEL_PREFIX = 'b'
|
3
|
+
|
4
|
+
autoload :Model, 'espresso/model'
|
5
|
+
autoload :Resources, 'espresso/resources'
|
6
|
+
autoload :ActionView, 'espresso/action_view'
|
7
|
+
autoload :ActionController, 'espresso/action_controller'
|
8
|
+
autoload :ResourcesHelpers, 'espresso/resources_helpers'
|
9
|
+
|
10
|
+
# Make a list of locale files, provided by gem
|
2
11
|
def self.locale_files
|
3
12
|
Dir[File.join(File.dirname(__FILE__), 'espresso', 'locales', '*')]
|
4
13
|
end
|
5
14
|
end
|
6
15
|
|
7
|
-
|
8
|
-
|
16
|
+
if defined?(ActiveRecord)
|
17
|
+
ActiveRecord::Base.send(:include, Espresso::Model)
|
18
|
+
end
|
9
19
|
|
10
|
-
if defined?
|
11
|
-
|
12
|
-
|
13
|
-
I18n.load_path.unshift(*Espresso.locale_files)
|
20
|
+
if defined?(ActionController)
|
21
|
+
ActionController::Base.send(:include, Espresso::ResourcesHelpers)
|
22
|
+
ActionController::Base.extend(Espresso::ActionController)
|
14
23
|
end
|
24
|
+
|
25
|
+
if defined?(ActionView)
|
26
|
+
ActionView::Base.send(:include, Espresso::ActionView)
|
27
|
+
end
|
28
|
+
|
29
|
+
require 'i18n'
|
30
|
+
I18n.load_path.unshift(*Espresso.locale_files)
|
31
|
+
|
32
|
+
require 'espresso/haml'
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: espresso
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 12
|
9
|
+
version: 0.1.12
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Alexander Semyonov
|
@@ -9,49 +14,77 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-03-25 00:00:00 +03:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
name: searchlogic
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
23
|
-
|
24
|
-
|
25
|
-
-
|
26
|
-
|
27
|
+
segments:
|
28
|
+
- 2
|
29
|
+
- 2
|
30
|
+
- 3
|
31
|
+
version: 2.2.3
|
27
32
|
type: :runtime
|
28
|
-
|
29
|
-
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: inherited_resources
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
38
|
requirements:
|
31
39
|
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
33
|
-
|
34
|
-
|
35
|
-
-
|
36
|
-
|
41
|
+
segments:
|
42
|
+
- 0
|
43
|
+
- 8
|
44
|
+
- 5
|
45
|
+
version: 0.8.5
|
37
46
|
type: :runtime
|
38
|
-
|
39
|
-
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: will_paginate
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
52
|
requirements:
|
41
53
|
- - ">="
|
42
54
|
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
|
55
|
+
segments:
|
56
|
+
- 2
|
57
|
+
- 3
|
58
|
+
- 11
|
59
|
+
version: 2.3.11
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
45
62
|
- !ruby/object:Gem::Dependency
|
46
|
-
name:
|
63
|
+
name: formtastic
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
- 9
|
72
|
+
- 7
|
73
|
+
version: 0.9.7
|
47
74
|
type: :runtime
|
48
|
-
|
49
|
-
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: shoulda
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
50
80
|
requirements:
|
51
81
|
- - ">="
|
52
82
|
- !ruby/object:Gem::Version
|
53
|
-
|
54
|
-
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
type: :development
|
87
|
+
version_requirements: *id005
|
55
88
|
description: Useful templates for controller and model functions
|
56
89
|
email: rotuka@tokak.ru
|
57
90
|
executables: []
|
@@ -70,11 +103,19 @@ files:
|
|
70
103
|
- espresso.gemspec
|
71
104
|
- init.rb
|
72
105
|
- lib/espresso.rb
|
73
|
-
- lib/espresso/
|
106
|
+
- lib/espresso/action_controller.rb
|
107
|
+
- lib/espresso/action_view.rb
|
108
|
+
- lib/espresso/action_view/form_builder.rb
|
109
|
+
- lib/espresso/action_view/navigation.rb
|
110
|
+
- lib/espresso/action_view/resources.rb
|
111
|
+
- lib/espresso/action_view/scopes.rb
|
112
|
+
- lib/espresso/action_view/stats.rb
|
113
|
+
- lib/espresso/haml.rb
|
74
114
|
- lib/espresso/locales/en.yml
|
75
115
|
- lib/espresso/locales/ru.yml
|
76
116
|
- lib/espresso/model.rb
|
77
|
-
- lib/espresso/
|
117
|
+
- lib/espresso/resources.rb
|
118
|
+
- lib/espresso/resources_helpers.rb
|
78
119
|
- test/espresso_test.rb
|
79
120
|
- test/test_helper.rb
|
80
121
|
has_rdoc: true
|
@@ -90,18 +131,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
131
|
requirements:
|
91
132
|
- - ">="
|
92
133
|
- !ruby/object:Gem::Version
|
134
|
+
segments:
|
135
|
+
- 0
|
93
136
|
version: "0"
|
94
|
-
version:
|
95
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
138
|
requirements:
|
97
139
|
- - ">="
|
98
140
|
- !ruby/object:Gem::Version
|
141
|
+
segments:
|
142
|
+
- 0
|
99
143
|
version: "0"
|
100
|
-
version:
|
101
144
|
requirements: []
|
102
145
|
|
103
146
|
rubyforge_project:
|
104
|
-
rubygems_version: 1.3.
|
147
|
+
rubygems_version: 1.3.6
|
105
148
|
signing_key:
|
106
149
|
specification_version: 3
|
107
150
|
summary: Rails extender to simplify rails development
|
data/lib/espresso/helpers.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
module Espresso
|
2
|
-
module Helpers
|
3
|
-
include WillPaginate::ViewHelpers
|
4
|
-
|
5
|
-
def simple_search
|
6
|
-
returning '' do |form|
|
7
|
-
form << form_tag(url_for(:action => :index), :method => :get)
|
8
|
-
form << content_tag(:table, :class => 'b_search') do
|
9
|
-
content_tag(:tr) do
|
10
|
-
returning '' do |result|
|
11
|
-
result << content_tag(:td,
|
12
|
-
content_tag(:div, text_field_tag(:q, params[:q], :type => 'search'), :class => 'b_input'),
|
13
|
-
:class => 'input')
|
14
|
-
result << content_tag(:td,
|
15
|
-
submit_tag(t('krasivotokak.espresso.find', :default => 'Find!'), :class => 'submit'),
|
16
|
-
:class => 'button')
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
form << yield if block_given?
|
21
|
-
form << '</form>'
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def will_paginate_with_i18n(collection, options = {})
|
26
|
-
will_paginate_without_i18n(collection,
|
27
|
-
options.merge({
|
28
|
-
:class => 'b_pagination',
|
29
|
-
:previous_label => t('krasivotokak.espresso.previous', :default => '← Previous'),
|
30
|
-
:next_label => t('krasivotokak.espresso.next', :default => 'Next →')}))
|
31
|
-
end
|
32
|
-
alias_method_chain :will_paginate, :i18n
|
33
|
-
end
|
34
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
require 'inherited_resources'
|
2
|
-
|
3
|
-
module Espresso
|
4
|
-
class ObjectsController < InheritedResources::Base
|
5
|
-
unloadable
|
6
|
-
|
7
|
-
# Same as default InheritedResources::Base#new, but render 'edit' view,
|
8
|
-
# other than 'new'
|
9
|
-
def new
|
10
|
-
new! do |format|
|
11
|
-
format.html { render 'edit' }
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
# Same as default InheritedResources::Base#create, but render 'edit' view,
|
16
|
-
# other than 'new'
|
17
|
-
def create
|
18
|
-
create! do |success, failure|
|
19
|
-
failure.html { render 'edit' }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
protected
|
24
|
-
|
25
|
-
# Find collection of objects with pagination.
|
26
|
-
# Also made Searchlogic object @search
|
27
|
-
#
|
28
|
-
# @return [WillPaginate::Collection] collection of objects
|
29
|
-
def collection
|
30
|
-
unless (result = get_collection_ivar).present?
|
31
|
-
@search, result = end_of_association_chain.search_results(params[:page], params[:query], params[:q])
|
32
|
-
set_collection_ivar(result)
|
33
|
-
end
|
34
|
-
result
|
35
|
-
end
|
36
|
-
|
37
|
-
# Build interpolation options for flash messages
|
38
|
-
def interpolation_options
|
39
|
-
{ :resource_title => resource.to_s }
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|