railsgarden-message_block 0.1.0

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.
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ * [0.1.0] Initial Version
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Ben Hughes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,59 @@
1
+ == Message Block
2
+
3
+ Implements the common view pattern by which a list of messages are shown at the top,
4
+ often a combination of flash messages and ActiveRecord validation issues on one or more models.
5
+ This allows for a nice, stylized block of messages at the top of the page with icons
6
+ indicating what type of message it is (error, confirmation, warning, etc.)
7
+
8
+ This view helper acts as a replacement for error_messages_for by taking error messages
9
+ from your models and combing them with flash messages (multiple types such as error, confirm, etc.)
10
+ and outputting them to your view. This plugin comes with an example stylesheet and images.
11
+
12
+ == Usage
13
+
14
+ Once you install this, you should now have a set of images at public/images/message_block and
15
+ a basic stylesheet installed at public/stylesheets/message_block.css. First you'll want to either
16
+ reference this in your layout or copy the declarations to your main layout. Then you can use
17
+ the helper <tt><%= message_block %></tt> as described below:
18
+
19
+ The first argument specifies a hash options:
20
+
21
+ * <tt>:on</tt> - specifies one or many model names for which to check error messages.
22
+ * <tt>:model_error_type</tt> - specifies the message type to use for validation errors; defaults to 'error'
23
+ * <tt>:flash_types</tt> - specifies the keys to check in the flash hash. Messages will be grouped in ul
24
+ lists according to this type. Defaults to: %w(back confirm error info warn)
25
+ * <tt>:html</tt> - Specifies HTML options for the containing div
26
+ * <tt>:id</tt> - Specifies ID of the containing div; defaults to 'message_block'
27
+ * <tt>:class</tt> - Specifies class name of the containing div; defaults to nothing.
28
+
29
+ === Example
30
+ Imagine you have a form for entering a user and a comment:
31
+
32
+ <%= message_block :on => [:user, :comment] %>
33
+
34
+ Imagine also you set these flash variables in the controller:
35
+ class CommentsController
36
+ def create
37
+ flash.now[:error] = "Error A"
38
+ flash.now[:confirm] = "Confirmation A" # Note you can use different types
39
+ flash.now[:warn] = ["Warn A", "Warn B"] # Can set to an array for multiple messages
40
+ end
41
+ end
42
+
43
+ And let's say that you want to show these messages but also show the validation issues
44
+ given that both user and comment fail ActiveRecord validation:
45
+
46
+ <div id="message_block">
47
+ <ul class="error">
48
+ <li>Error A</li>
49
+ <li>User first name is required.</li>
50
+ <li>Comment contents is required.</li>
51
+ </ul>
52
+ <ul class="confirm">
53
+ <li>Confirmation A</li>
54
+ </ul>
55
+ <ul class="warn">
56
+ <li>Warn A</li>
57
+ <li>Warn B</li>
58
+ </ul>
59
+ </div>
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'echoe'
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+
7
+ desc 'Default: run unit tests.'
8
+ task :default => :test
9
+
10
+ desc 'Test the message_block plugin.'
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << 'lib'
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = true
16
+ end
17
+
18
+ desc 'Generate documentation for the message_block plugin.'
19
+ Rake::RDocTask.new(:rdoc) do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'MessageBlock'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+
28
+ Echoe.new('message_block', '0.1.0') do |p|
29
+ p.description = "Handle multiple flash messages and ActiveRecord validation errors with ease."
30
+ p.url = "http://github.com/railsgarden/message_block"
31
+ p.author = "Ben Hughes"
32
+ p.email = "ben@railsgarden.com"
33
+ p.ignore_pattern = ["tmp/*", "script/*"]
34
+ p.development_dependencies = []
35
+ end
36
+
37
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
38
+
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,38 @@
1
+ #message_block {
2
+ clear: both;
3
+ margin-top: 0.2em;
4
+ margin-bottom: 0.3em;
5
+ }
6
+
7
+ #message_block ul {
8
+ margin-bottom: 0;
9
+ list-style: none;
10
+ padding: 4px;
11
+ }
12
+ #message_block ul li {
13
+ margin-left: 3em;
14
+ }
15
+
16
+ #message_block ul.error {
17
+ border-top: 1px solid #ecd757;
18
+ border-bottom: 1px solid #ecd757;
19
+ background: #fcf6d0 url(../../images/message_block/error_m.gif) 1em 50% no-repeat;
20
+ }
21
+
22
+ #message_block ul.info {
23
+ border-top: 1px solid #ecd757;
24
+ border-bottom: 1px solid #ecd757;
25
+ background: #fcf6d0 url(../../images/message_block/info_m.gif) 1em 50% no-repeat;
26
+ }
27
+
28
+ #message_block ul.confirm {
29
+ border-top: 1px solid #ecd757;
30
+ border-bottom: 1px solid #ecd757;
31
+ background: #fcf6d0 url(../../images/message_block/confirmation_m.gif) 1em 50% no-repeat;
32
+ }
33
+
34
+ #message_block ul.warn {
35
+ border-top: 1px solid #ecd757;
36
+ border-bottom: 1px solid #ecd757;
37
+ background: #fcf6d0 url(../../images/message_block/warn_m.gif) 1em 50% no-repeat;
38
+ }
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'message_block'
data/install.rb ADDED
@@ -0,0 +1,21 @@
1
+ puts "Copying assets..."
2
+
3
+ images_source = File.join(File.dirname(__FILE__), "assets", "images")
4
+ stylesheets_source = File.join(File.dirname(__FILE__), "assets", "stylesheets", "message_block.css")
5
+
6
+ images_target = File.join(RAILS_ROOT, "public", "images", "message_block")
7
+ stylesheets_target = File.join(RAILS_ROOT, "public", "stylesheets", "message_block.css")
8
+
9
+ unless File.exists?(images_target)
10
+ FileUtils.cp_r(images_source, images_target)
11
+ puts " Copied Images"
12
+ else
13
+ puts " Images appear to already be installed, not copying."
14
+ end
15
+
16
+ unless File.exists?(stylesheets_target)
17
+ FileUtils.cp(stylesheets_source, stylesheets_target)
18
+ puts " Copied Stylesheet"
19
+ else
20
+ puts " Stylesheet appears to already be installed, not copying"
21
+ end
@@ -0,0 +1,3 @@
1
+ require_dependency 'message_block/helpers'
2
+
3
+ ActionView::Base.send(:include, Rubiety::MessageBlock::Helpers)
@@ -0,0 +1,51 @@
1
+ module Rubiety
2
+ module MessageBlock
3
+ module Helpers
4
+
5
+ def message_block(options = {})
6
+ options.assert_valid_keys(:on, :model_error_type, :flash_types, :html, :id, :class)
7
+
8
+ options[:model_error_type] ||= :error
9
+ options[:flash_types] ||= [:back, :confirm, :error, :info, :warn]
10
+ options[:on] ||= controller.controller_name.split('/').last.gsub(/\_controller$/, '').singularize.to_sym
11
+ options[:html] ||= {:id => 'message_block'}
12
+ options[:html][:id] = options[:id] if options[:id]
13
+ options[:html][:class] = options[:class] if options[:class]
14
+
15
+ flash_messages = {}
16
+
17
+ options[:flash_types].each do |type|
18
+ entries = flash[type.to_sym]
19
+ next if entries.nil?
20
+ entries = [entries] unless entries.is_a?(Array)
21
+
22
+ flash_messages[type.to_sym] ||= []
23
+ flash_messages[type.to_sym] += entries
24
+ end
25
+
26
+ options[:on] = [options[:on]] unless options[:on].is_a?(Array)
27
+
28
+ options[:on] = [options[:on]] unless options[:on].is_a?(Array)
29
+ model_objects = options[:on].map do |model_object|
30
+ if model_object.instance_of?(String) or model_object.instance_of?(Symbol)
31
+ instance_variable_get("@#{model_object}")
32
+ else
33
+ model_object
34
+ end
35
+ end.select {|m| !m.nil? }
36
+
37
+ model_errors = model_objects.inject([]) {|b, m| b += m.errors.full_messages }
38
+
39
+ flash_messages[options[:model_error_type].to_sym] ||= []
40
+ flash_messages[options[:model_error_type].to_sym] += model_errors
41
+
42
+ contents = flash_messages.keys.select {|type| !flash_messages[type.to_sym].empty? }.map do |type|
43
+ content_tag(:ul, flash_messages[type.to_sym].map {|message| content_tag(:li, message) }.join, :class => type)
44
+ end.join
45
+
46
+ content_tag(:div, contents, options[:html])
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{message_block}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ben Hughes"]
9
+ s.date = %q{2009-01-16}
10
+ s.description = %q{Handle multiple flash messages and ActiveRecord validation errors with ease.}
11
+ s.email = %q{ben@railsgarden.com}
12
+ s.extra_rdoc_files = ["CHANGELOG", "lib/message_block/helpers.rb", "lib/message_block.rb", "README.rdoc"]
13
+ s.files = ["assets/images/back.gif", "assets/images/back_m.gif", "assets/images/confirmation.gif", "assets/images/confirmation_m.gif", "assets/images/error.gif", "assets/images/error_m.gif", "assets/images/info.gif", "assets/images/info_m.gif", "assets/images/warn.gif", "assets/images/warn_m.gif", "assets/stylesheets/message_block.css", "CHANGELOG", "init.rb", "install.rb", "lib/message_block/helpers.rb", "lib/message_block.rb", "MIT-LICENSE", "Rakefile", "README.rdoc", "test/message_block_helper_test.rb", "Manifest", "message_block.gemspec"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://github.com/railsgarden/message_block}
16
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Message_block", "--main", "README.rdoc"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{message_block}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{Handle multiple flash messages and ActiveRecord validation errors with ease.}
21
+ s.test_files = ["test/message_block_helper_test.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 2
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ else
29
+ end
30
+ else
31
+ end
32
+ end
@@ -0,0 +1,193 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'action_pack'
4
+ require 'action_view'
5
+
6
+ $:.unshift File.dirname(__FILE__) + '/../lib'
7
+ require File.dirname(__FILE__) + '/../init'
8
+
9
+ class MessageBlockHelperTest < Test::Unit::TestCase
10
+ include ActionView::Helpers::TagHelper
11
+ include Rubiety::MessageBlock::Helpers
12
+
13
+ # Borrowed model stubs from Rails active_record_helper_test.rb
14
+ # TODO: Re-implement using mocha
15
+ Post = Struct.new("Post", :title, :author_name)
16
+ User = Struct.new("User", :email)
17
+
18
+ def setup_post
19
+ @post = Post.new
20
+ def @post.errors
21
+ Class.new do
22
+ def on(field)
23
+ case field.to_s
24
+ when "author_name"
25
+ "can't be empty"
26
+ when "body"
27
+ true
28
+ else
29
+ false
30
+ end
31
+ end
32
+ def empty?() false end
33
+ def count() 1 end
34
+ def full_messages() [ "Author name can't be empty" ] end
35
+ end.new
36
+ end
37
+
38
+ @post.title = "Hello World"
39
+ @post.author_name = ""
40
+ end
41
+
42
+ def setup_user
43
+ @user = User.new
44
+ def @user.errors
45
+ Class.new {
46
+ def on(field) field == "email" end
47
+ def empty?() false end
48
+ def count() 1 end
49
+ def full_messages() [ "User email can't be empty" ] end
50
+ }.new
51
+ end
52
+
53
+ @user.email = ""
54
+ end
55
+
56
+ def controller
57
+ @controller ||= Class.new {
58
+ def controller_name
59
+ "widgets_controller"
60
+ end
61
+ }.new
62
+ end
63
+
64
+ def posts_controller
65
+ Class.new {
66
+ def controller_name
67
+ "posts_controller"
68
+ end
69
+ }.new
70
+ end
71
+
72
+ def flash
73
+ @flash ||= {}
74
+ end
75
+
76
+
77
+ def setup
78
+ setup_post
79
+ setup_user
80
+ end
81
+
82
+
83
+ ### Generic Invocation
84
+ def test_doesnt_accept_invalid_options
85
+ assert_raise(ArgumentError) { message_block :invalid => 'value' }
86
+ end
87
+
88
+ def test_accepts_valid_options
89
+ assert_nothing_raised do
90
+ message_block :on => :post,
91
+ :model_error_type => "fail",
92
+ :flash_types => %w(error warn),
93
+ :html => {:style => 'height: 10em'},
94
+ :id => "block",
95
+ :class => "messages"
96
+ end
97
+ end
98
+
99
+
100
+ ### Grabbing model errors functionality
101
+ def test_without_errors_should_show_nothing
102
+ expected = %(<div id="message_block"></div>)
103
+ assert_equal expected, message_block
104
+ end
105
+
106
+ def test_automatically_find_post_errors_with_posts_controller
107
+ @controller = posts_controller
108
+ expected = %(<div id="message_block"><ul class="error"><li>Author name can't be empty</li></ul></div>)
109
+ assert_equal expected, message_block
110
+ end
111
+
112
+ def test_gives_error_for_post
113
+ expected = %(<div id="message_block"><ul class="error"><li>Author name can't be empty</li></ul></div>)
114
+ assert_equal expected, message_block(:on => :post)
115
+ end
116
+
117
+ def test_gives_error_for_user
118
+ expected = %(<div id="message_block"><ul class="error"><li>User email can't be empty</li></ul></div>)
119
+ assert_equal expected, message_block(:on => :user)
120
+ end
121
+
122
+ def test_gives_both_errors_for_post_and_user
123
+ expected = %(<div id="message_block"><ul class="error"><li>Author name can't be empty</li><li>User email can't be empty</li></ul></div>)
124
+ assert_equal expected, message_block(:on => [:post, :user])
125
+ end
126
+
127
+ def test_gives_both_errors_for_post_and_user_in_correct_order
128
+ expected = %(<div id="message_block"><ul class="error"><li>User email can't be empty</li><li>Author name can't be empty</li></ul></div>)
129
+ assert_equal expected, message_block(:on => [:user, :post])
130
+ end
131
+
132
+ def test_gives_error_for_user_given_direct_instance_variable
133
+ expected = %(<div id="message_block"><ul class="error"><li>User email can't be empty</li></ul></div>)
134
+ assert_equal expected, message_block(:on => @user)
135
+ end
136
+
137
+ def test_respects_model_error_type
138
+ expected = %(<div id="message_block"><ul class="fail"><li>User email can't be empty</li></ul></div>)
139
+ assert_equal expected, message_block(:on => :user, :model_error_type => "fail")
140
+ end
141
+
142
+
143
+ ### Extending HTML options for containing div functionality
144
+ def test_can_specify_id_for_containing_div
145
+ expected = %(<div id="messages"></div>)
146
+ assert_equal expected, message_block(:id => "messages")
147
+ end
148
+
149
+ def test_can_specify_class_for_containing_div
150
+ expected = %(<div class="messages" id="message_block"></div>)
151
+ assert_equal expected, message_block(:class => "messages")
152
+ end
153
+
154
+ def test_can_specify_html_options_for_containing_div
155
+ expected = %(<div class="messages" id="block"></div>)
156
+ assert_equal expected, message_block(:html => {:id => "block", :class => "messages"})
157
+ end
158
+
159
+
160
+ ### Flash messages functionality
161
+ def test_sees_flash_error_string
162
+ flash[:error] = "Error A"
163
+ expected = %(<div id="message_block"><ul class="error"><li>Error A</li></ul></div>)
164
+ assert_equal expected, message_block
165
+ end
166
+
167
+ def test_sees_flash_error_array
168
+ flash[:error] = ["Error A", "Error B"]
169
+ expected = %(<div id="message_block"><ul class="error"><li>Error A</li><li>Error B</li></ul></div>)
170
+ assert_equal expected, message_block
171
+ end
172
+
173
+ def test_sees_default_flash_types
174
+ default_types = [:back, :confirm, :error, :info, :warn]
175
+ default_types.each do |type|
176
+ flash[type] = type.to_s
177
+ end
178
+
179
+ expected_contents = default_types.map do |type|
180
+ content_tag(:ul, content_tag(:li, type.to_s), :class => type.to_s)
181
+ end.join
182
+
183
+ expected = %(<div id="message_block">#{expected_contents}</div>)
184
+ assert_equal expected, message_block
185
+ end
186
+
187
+ def test_sees_flash_error_alongside_model_error
188
+ flash[:error] = "Error A"
189
+ expected = %(<div id="message_block"><ul class="error"><li>Error A</li><li>Author name can't be empty</li></ul></div>)
190
+ assert_equal expected, message_block(:on => :post)
191
+ end
192
+
193
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: railsgarden-message_block
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Hughes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-16 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Handle multiple flash messages and ActiveRecord validation errors with ease.
17
+ email: ben@railsgarden.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - CHANGELOG
24
+ - lib/message_block/helpers.rb
25
+ - lib/message_block.rb
26
+ - README.rdoc
27
+ files:
28
+ - assets/images/back.gif
29
+ - assets/images/back_m.gif
30
+ - assets/images/confirmation.gif
31
+ - assets/images/confirmation_m.gif
32
+ - assets/images/error.gif
33
+ - assets/images/error_m.gif
34
+ - assets/images/info.gif
35
+ - assets/images/info_m.gif
36
+ - assets/images/warn.gif
37
+ - assets/images/warn_m.gif
38
+ - assets/stylesheets/message_block.css
39
+ - CHANGELOG
40
+ - init.rb
41
+ - install.rb
42
+ - lib/message_block/helpers.rb
43
+ - lib/message_block.rb
44
+ - MIT-LICENSE
45
+ - Rakefile
46
+ - README.rdoc
47
+ - test/message_block_helper_test.rb
48
+ - Manifest
49
+ - message_block.gemspec
50
+ has_rdoc: true
51
+ homepage: http://github.com/railsgarden/message_block
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --line-numbers
55
+ - --inline-source
56
+ - --title
57
+ - Message_block
58
+ - --main
59
+ - README.rdoc
60
+ require_paths:
61
+ - lib
62
+ required_ruby_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ version: "1.2"
73
+ version:
74
+ requirements: []
75
+
76
+ rubyforge_project: message_block
77
+ rubygems_version: 1.2.0
78
+ signing_key:
79
+ specification_version: 2
80
+ summary: Handle multiple flash messages and ActiveRecord validation errors with ease.
81
+ test_files:
82
+ - test/message_block_helper_test.rb