smarter_listing 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +77 -0
  4. data/Rakefile +32 -0
  5. data/app/views/smart_listing/_action_copy.html.erb +3 -0
  6. data/app/views/smarter_listing/_form_logic.js +1 -0
  7. data/app/views/smarter_listing/copy.js.erb +2 -0
  8. data/app/views/smarter_listing/create.js.erb +1 -0
  9. data/app/views/smarter_listing/destroy.js.erb +2 -0
  10. data/app/views/smarter_listing/edit.js.erb +2 -0
  11. data/app/views/smarter_listing/index.js.erb +1 -0
  12. data/app/views/smarter_listing/new.js.erb +2 -0
  13. data/app/views/smarter_listing/update.js.erb +1 -0
  14. data/lib/smarter_listing.rb +7 -0
  15. data/lib/smarter_listing/controller_extension.rb +77 -0
  16. data/lib/smarter_listing/engine.rb +4 -0
  17. data/lib/smarter_listing/helper.rb +92 -0
  18. data/lib/smarter_listing/loader.rb +25 -0
  19. data/lib/smarter_listing/version.rb +3 -0
  20. data/lib/tasks/smarter_listing_tasks.rake +4 -0
  21. data/test/controllers/listings_controller_test.rb +57 -0
  22. data/test/dummy/README.rdoc +28 -0
  23. data/test/dummy/Rakefile +6 -0
  24. data/test/dummy/app/assets/javascripts/application.js +13 -0
  25. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  26. data/test/dummy/app/controllers/application_controller.rb +5 -0
  27. data/test/dummy/app/controllers/listings_controller.rb +7 -0
  28. data/test/dummy/app/helpers/application_helper.rb +2 -0
  29. data/test/dummy/app/models/listing.rb +2 -0
  30. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/test/dummy/app/views/listings/_form.html.erb +8 -0
  32. data/test/dummy/app/views/listings/_listing.html.erb +5 -0
  33. data/test/dummy/app/views/listings/_table_header.html.erb +14 -0
  34. data/test/dummy/app/views/listings/index.html.erb +8 -0
  35. data/test/dummy/bin/bundle +3 -0
  36. data/test/dummy/bin/rails +4 -0
  37. data/test/dummy/bin/rake +4 -0
  38. data/test/dummy/config.ru +4 -0
  39. data/test/dummy/config/application.rb +23 -0
  40. data/test/dummy/config/boot.rb +5 -0
  41. data/test/dummy/config/database.yml +25 -0
  42. data/test/dummy/config/environment.rb +5 -0
  43. data/test/dummy/config/environments/development.rb +37 -0
  44. data/test/dummy/config/environments/production.rb +82 -0
  45. data/test/dummy/config/environments/test.rb +39 -0
  46. data/test/dummy/config/initializers/assets.rb +8 -0
  47. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  48. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  49. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  50. data/test/dummy/config/initializers/inflections.rb +16 -0
  51. data/test/dummy/config/initializers/mime_types.rb +4 -0
  52. data/test/dummy/config/initializers/session_store.rb +3 -0
  53. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  54. data/test/dummy/config/locales/en.yml +23 -0
  55. data/test/dummy/config/routes.rb +5 -0
  56. data/test/dummy/config/secrets.yml +22 -0
  57. data/test/dummy/db/development.sqlite3 +0 -0
  58. data/test/dummy/db/migrate/20140724101100_create_listings.rb +11 -0
  59. data/test/dummy/db/schema.rb +24 -0
  60. data/test/dummy/db/test.sqlite3 +0 -0
  61. data/test/dummy/log/development.log +16 -0
  62. data/test/dummy/log/test.log +21360 -0
  63. data/test/fixtures/listings.yml +4 -0
  64. data/test/helpers/smarter_listing_loader_test.rb +39 -0
  65. data/test/test_helper.rb +17 -0
  66. metadata +196 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db91ff26a056d22121a2ef300d8c9d2efbd3fc2c
4
+ data.tar.gz: 0a28a1db18c045428979eec8c134ace962a99893
5
+ SHA512:
6
+ metadata.gz: bfee046a907d192110fa45c9f9f6538b5394ba09119c287594f2a271b463fe80acf7d9dfd340bac8b432ea768d70cffffcd79e6d1ada354bd4606b01ee205908
7
+ data.tar.gz: 03fca7d00ecf4a9fd57b5046fe737aee26e22a9be37a0ebe5f31d78acff9c26f8ffd208d831e9c03bffe46a1218a92661af5d3e5fbde0f4a271ad26855ae7c60
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2014 YOURNAME
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.md ADDED
@@ -0,0 +1,77 @@
1
+ [![Build Status](https://travis-ci.org/MichaelSp/smarter_listing.svg?branch=master)](https://travis-ci.org/MichaelSp/smarter_listing)
2
+
3
+ SmarterListing
4
+ ================
5
+
6
+ The [smart listing](http://showcase.sology.eu/smart_listing) from the guys at Sology is a real productivity boost.
7
+ But it's too verbose to include it into your rails app. This gem makes smart listing even smarter. It drys your controller out.
8
+
9
+ Usage
10
+ -----
11
+
12
+ * Gemfile
13
+ ```ruby
14
+ gem 'smarter_listing'
15
+ ```
16
+ then `bundle install`
17
+
18
+ * app/controllers/posts_controller.rb
19
+ ```ruby
20
+ class PostController < ApplicationController
21
+ smarter_listing
22
+
23
+ # Look ma, no controller actions needs to be defined
24
+
25
+ private
26
+ def resource_params
27
+ params.require(:post).permit(:title, :body) if params[:post]
28
+ end
29
+ end
30
+ ```
31
+
32
+ * app/views/posts/_form.html.haml
33
+ ```ruby
34
+ = bootstrap_form_for @post # this requires the fine gem 'bootstrap_form'. Check it out!
35
+ = f.text_field :title
36
+ = f.text_area :body
37
+ .pull-right
38
+ = f.primary
39
+ = link_to 'Cancel'. posts_path, class: 'btn btn-default'
40
+ ```
41
+
42
+ * app/views/posts/_post.html.haml
43
+ ```ruby
44
+ %td= object.title.truncate(30)
45
+ %td= object.body.truncate(80)
46
+ %td.actions= smart_listing_item_actions [action_copy(object,copy_post_path(object)),action_edit(object,edit_post_path(object)),action_destroy(object,post_path(object))]
47
+ ```
48
+
49
+ * app/views/posts/_table_header.html.haml
50
+ ```ruby
51
+ %table.table.table-striped
52
+ %tr
53
+ %th= smart_listing.sortable t("Created"), :created_at
54
+ %th= smart_listing.sortable t("Title"), :title
55
+ %th= smart_listing.sortable t("Body"), :body
56
+ %th
57
+ - smart_listing.collection.each do |post|
58
+ %tr.editable{data: {id: post.id}}
59
+ = smart_listing.render partial: 'posts/post', locals: {object: post}
60
+
61
+ = smart_listing.item_new colspan: 11, link: new_post_path
62
+
63
+ = smart_listing.paginate
64
+ = smart_listing.pagination_per_page_links
65
+ ```
66
+
67
+ * app/views/posts/index.html.haml
68
+ ```ruby
69
+ = smart_listing_controls_for(:posts, {class: "form-inline text-right"}) do
70
+ .form-group.filter.input-append
71
+ = text_field_tag :filter, '', class: "search form-control", placeholder: t("Search..."), autocomplete: :off
72
+
73
+ %button.btn.btn-primary.disabled{type: :submit}
74
+ =fa_icon 'search' # this requires gem 'font-awesome-rails'
75
+ =smart_listing_render(:posts)
76
+
77
+ ```
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'SmarterListing'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
22
+ require 'rake/testtask'
23
+
24
+ Rake::TestTask.new(:test) do |t|
25
+ t.libs << 'lib'
26
+ t.libs << 'test'
27
+ t.pattern = 'test/**/*_test.rb'
28
+ t.verbose = false
29
+ end
30
+
31
+
32
+ task default: :test
@@ -0,0 +1,3 @@
1
+ <%=link_to action[:custom_url], {class: action[:name], title: action[:custom_title], remote: true, method: :put}, action[:html_options] do %>
2
+ <i class="<%= action[:custom_icon] %>"></i>
3
+ <% end %>
@@ -0,0 +1 @@
1
+ $('.select2').select2().removeClass('form-control');
@@ -0,0 +1,2 @@
1
+ <%= smart_listing_item collection_sym, :copy, resource, "#{current_engine}/#{collection_sym}/form" %>
2
+ <%== render 'application/form_logic' %>
@@ -0,0 +1 @@
1
+ <%= smart_listing_item collection_sym, :create, resource, resource.valid? ? "#{current_engine}/#{collection_sym}/#{collection_action}" : "#{current_engine}/#{collection_sym}/form" %>
@@ -0,0 +1,2 @@
1
+ <%= smart_listing_item collection_sym, :destroy, resource %>
2
+
@@ -0,0 +1,2 @@
1
+ <%= smart_listing_item collection_sym, :edit, resource, "#{current_engine}/#{collection_sym}/form" %>
2
+ <%== render 'smarter_listing/form_logic' %>
@@ -0,0 +1 @@
1
+ <%= smart_listing_update(collection_sym) %>
@@ -0,0 +1,2 @@
1
+ <%= smart_listing_item collection_sym, :new, resource, "#{current_engine}/#{collection_sym}/form" %>
2
+ <%== render 'smarter_listing/form_logic' %>
@@ -0,0 +1 @@
1
+ <%= smart_listing_item collection_sym, :update, resource, resource.valid? ? "#{current_engine}/#{collection_sym}/#{collection_action}" : "#{current_engine}/#{collection_sym}/form" %>
@@ -0,0 +1,7 @@
1
+ require 'smarter_listing/engine'
2
+ require 'smarter_listing/loader'
3
+
4
+ module SmarterListing
5
+ autoload :Helper, 'smarter_listing/helper'
6
+ autoload :ControllerExtension, 'smarter_listing/controller_extension'
7
+ end
@@ -0,0 +1,77 @@
1
+ module SmarterListing::ControllerExtension
2
+
3
+ def self.included base
4
+ base.helper_method :collection, :resource
5
+ base.include SmarterListing::Helper
6
+ base.class_eval do
7
+ # Actions
8
+ define_method :index do
9
+ collection
10
+ respond_to do |format|
11
+ format.html
12
+ format.js { render action: 'index.js.erb' }
13
+ end
14
+ end
15
+
16
+ define_method :new do
17
+ instance_variable_get(resource_ivar) || instance_variable_set(resource_ivar, model.new(resource_params))
18
+ render 'smarter_listing/new'
19
+ end
20
+
21
+ define_method :create do
22
+ instance_variable_get(resource_ivar) || instance_variable_set(resource_ivar, model.create(resource_params))
23
+ render 'smarter_listing/create'
24
+ end
25
+
26
+ define_method :copy do
27
+ instance_variable_set resource_ivar, resource.dup
28
+ render 'smarter_listing/copy'
29
+ end
30
+
31
+ define_method :show do
32
+ resource
33
+ render resource, object: resource
34
+ end
35
+
36
+ define_method :edit do
37
+ resource
38
+ render 'smarter_listing/edit'
39
+ end
40
+
41
+ define_method :update do
42
+ resource.update resource_params
43
+ render 'smarter_listing/update'
44
+ end
45
+
46
+ define_method :destroy do
47
+ resource.destroy
48
+ render 'smarter_listing/destroy'
49
+ end
50
+ end
51
+ end
52
+
53
+ def filter_parameter
54
+ self.class.instance_variable_get :@filter_parameter
55
+ end
56
+
57
+ def filtered(model)
58
+ (!params[filter_parameter].blank?) ? model.search { fulltext "#{params[filter_parameter]}" }.results : model.all
59
+ end
60
+
61
+ def load_collection
62
+ instance_variable_set collection_ivar, smart_listing_create(collection_sym, filtered(model), partial: "#{current_engine}/#{collection_sym}/table_header")
63
+ end
64
+
65
+ def load_resource
66
+ instance_variable_set resource_ivar, (model.find(params[:id]) rescue (action_name == 'new' ? model.new(resource_params) : nil))
67
+ end
68
+
69
+ def resource
70
+ instance_variable_get(resource_ivar) || load_resource
71
+ end
72
+
73
+ def collection
74
+ instance_variable_get(collection_ivar) || load_collection
75
+ end
76
+
77
+ end
@@ -0,0 +1,4 @@
1
+ module SmarterListing
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,92 @@
1
+ module SmarterListing
2
+ module Helper
3
+
4
+ # def self.included base
5
+ # base.helper_method :collection_sym, :collection_action, :collection_ivar, :resource_sym, :resource_ivar, :model
6
+ # base.helper_method :action_copy, :action_edit, :action_destroy, :current_engine
7
+ # end
8
+
9
+ def collection_sym
10
+ @collection_sym = nil
11
+ @collection_sym ||= model.to_s.underscore.downcase.pluralize.to_sym
12
+ end
13
+
14
+ def collection_action
15
+ @collection_action = nil
16
+ @collection_action ||= model.to_s.underscore.downcase.singularize.to_sym
17
+ end
18
+
19
+ def collection_ivar
20
+ "@#{collection_sym}"
21
+ end
22
+
23
+ def resource_sym
24
+ @resource_sym ||= model.to_s.underscore.downcase.to_sym
25
+ end
26
+
27
+ def resource_ivar
28
+ "@#{resource_sym}"
29
+ end
30
+
31
+ def current_engine
32
+ self.class.parent == Object ? '' : self.class.parent.to_s.downcase
33
+ end
34
+
35
+ def model
36
+ @model = nil
37
+ @model ||= begin
38
+ # First priority is the namespaced model, e.g. User::Group
39
+ resource_class ||= begin
40
+ namespaced_class = self.name.sub(/Controller/, '').singularize
41
+ namespaced_class.constantize
42
+ rescue NameError
43
+ nil
44
+ end
45
+
46
+ # Second priority is the top namespace model, e.g. EngineName::Article for EngineName::Admin::ArticlesController
47
+ resource_class ||= begin
48
+ namespaced_classes = self.name.sub(/Controller/, '').split('::')
49
+ namespaced_class = [namespaced_classes.first, namespaced_classes.last].join('::').singularize
50
+ namespaced_class.constantize
51
+ rescue NameError
52
+ nil
53
+ end
54
+
55
+ # Third priority the camelcased c, i.e. UserGroup
56
+ resource_class ||= begin
57
+ camelcased_class = self.name.sub(/Controller/, '').gsub('::', '').singularize
58
+ camelcased_class.constantize
59
+ rescue NameError
60
+ nil
61
+ end
62
+
63
+ # Otherwise use the Group class, or fail
64
+ resource_class ||= begin
65
+ class_name = self.controller_name.classify
66
+ class_name.constantize
67
+ rescue NameError => e
68
+ raise unless e.message.include?(class_name)
69
+ nil
70
+ end
71
+ resource_class
72
+ end
73
+ end
74
+
75
+ def action_copy(object, path)
76
+ {
77
+ name: :copy,
78
+ custom_url: path,
79
+ custom_icon: SmartListing.config.classes(:icon_copy),
80
+ custom_title: 'Copy'
81
+ }
82
+ end
83
+
84
+ def action_edit(object, path)
85
+ {name: :edit, url: path}
86
+ end
87
+
88
+ def action_destroy(object, path)
89
+ {name: :destroy, url: path}
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,25 @@
1
+ require 'smart_listing'
2
+ require 'kaminari'
3
+
4
+ module SmarterListing
5
+ module Loader
6
+ def initialize
7
+
8
+ end
9
+
10
+ def self.extended base
11
+ def smarter_listing(filter_parameter = :filter)
12
+ helper SmartListing::Helper
13
+ include SmartListing::Helper::ControllerExtensions
14
+
15
+ helper SmarterListing::Helper
16
+ include SmarterListing::ControllerExtension
17
+
18
+ instance_variable_set :@filter_parameter, filter_parameter
19
+ prepend Loader
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ ActionController::Base.extend SmarterListing::Loader
@@ -0,0 +1,3 @@
1
+ module SmarterListing
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :smarter_listing do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,57 @@
1
+ require 'test_helper'
2
+
3
+ require 'smarter_listing'
4
+
5
+ class ListingsControllerTest < ActionController::TestCase
6
+ setup do
7
+ @listing = listings(:one)
8
+ ListingsController.smarter_listing
9
+ end
10
+
11
+ test 'should have the methods from all helpers' do
12
+ assert_includes @controller.methods, :create
13
+ assert_includes @controller.methods, :show
14
+ assert_includes @controller.methods, :update
15
+ assert_includes @controller.methods, :destroy
16
+ assert_includes @controller.methods, :new
17
+ end
18
+
19
+ test "should get index" do
20
+ get :index
21
+ assert_response :success
22
+ assert_not_nil assigns(:listings)
23
+ end
24
+
25
+ test "should get new" do
26
+ xhr :get, :new, format: :js
27
+ assert_response :success
28
+ end
29
+
30
+ test "should create listing" do
31
+ assert_difference('Listing.count') do
32
+ resource_params = {content: @listing.content, deleted_at: @listing.deleted_at, name: 'newName'}
33
+ xhr :post, :create, listing: resource_params, format: :js
34
+ assert_empty @listing.errors
35
+ end
36
+ assert_response :success
37
+ end
38
+
39
+ test "should get edit" do
40
+ xhr :get, :edit, id: @listing, format: :js
41
+ assert_response :success
42
+ end
43
+
44
+ test "should update listing" do
45
+ resource_params = {content: @listing.content, deleted_at: @listing.deleted_at, name: 'newName'}
46
+ xhr :patch, :update, id: @listing, listing: resource_params, format: :js
47
+ assert_empty @listing.errors
48
+ assert_response :success
49
+ end
50
+
51
+ test "should destroy listing" do
52
+ assert_difference('Listing.count', -1) do
53
+ xhr :delete, :destroy, id: @listing, format: :js
54
+ end
55
+ assert_response :success
56
+ end
57
+ end