auto_presenter 0.0.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 (69) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +51 -0
  4. data/Rakefile +29 -0
  5. data/lib/auto_presenter.rb +49 -0
  6. data/lib/auto_presenter/relation_presenter.rb +31 -0
  7. data/lib/auto_presenter/version.rb +3 -0
  8. data/test/dummy/README.rdoc +28 -0
  9. data/test/dummy/Rakefile +6 -0
  10. data/test/dummy/app/assets/javascripts/application.js +13 -0
  11. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  12. data/test/dummy/app/controllers/application_controller.rb +3 -0
  13. data/test/dummy/app/controllers/projects_controller.rb +64 -0
  14. data/test/dummy/app/controllers/tasks_controller.rb +43 -0
  15. data/test/dummy/app/helpers/application_helper.rb +2 -0
  16. data/test/dummy/app/helpers/projects_helper.rb +2 -0
  17. data/test/dummy/app/helpers/tasks_helper.rb +2 -0
  18. data/test/dummy/app/models/project.rb +3 -0
  19. data/test/dummy/app/models/task.rb +10 -0
  20. data/test/dummy/app/presenters/project_presenter.rb +2 -0
  21. data/test/dummy/app/presenters/projects/completed_tasks_presenter.rb +2 -0
  22. data/test/dummy/app/presenters/projects/projects_presenter.rb +2 -0
  23. data/test/dummy/app/presenters/task_presenter.rb +6 -0
  24. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  25. data/test/dummy/app/views/projects/_form.html.erb +21 -0
  26. data/test/dummy/app/views/projects/edit.html.erb +6 -0
  27. data/test/dummy/app/views/projects/index.html.erb +25 -0
  28. data/test/dummy/app/views/projects/new.html.erb +5 -0
  29. data/test/dummy/app/views/projects/show.html.erb +33 -0
  30. data/test/dummy/app/views/tasks/_task.html +1 -0
  31. data/test/dummy/bin/bundle +3 -0
  32. data/test/dummy/bin/rails +4 -0
  33. data/test/dummy/bin/rake +4 -0
  34. data/test/dummy/config.ru +4 -0
  35. data/test/dummy/config/application.rb +23 -0
  36. data/test/dummy/config/boot.rb +5 -0
  37. data/test/dummy/config/database.yml +30 -0
  38. data/test/dummy/config/environment.rb +5 -0
  39. data/test/dummy/config/environments/development.rb +37 -0
  40. data/test/dummy/config/environments/production.rb +83 -0
  41. data/test/dummy/config/environments/test.rb +39 -0
  42. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  43. data/test/dummy/config/initializers/inflections.rb +16 -0
  44. data/test/dummy/config/initializers/mime_types.rb +5 -0
  45. data/test/dummy/config/initializers/secret_token.rb +1 -0
  46. data/test/dummy/config/initializers/session_store.rb +3 -0
  47. data/test/dummy/config/locales/en.yml +23 -0
  48. data/test/dummy/config/routes.rb +6 -0
  49. data/test/dummy/config/secrets.yml +22 -0
  50. data/test/dummy/db/migrate/20140517101419_create_projects_and_tasks.rb +19 -0
  51. data/test/dummy/db/schema.rb +31 -0
  52. data/test/dummy/db/test.sqlite3 +0 -0
  53. data/test/dummy/log/development.log +1284 -0
  54. data/test/dummy/log/test.log +7437 -0
  55. data/test/dummy/public/404.html +67 -0
  56. data/test/dummy/public/422.html +67 -0
  57. data/test/dummy/public/500.html +66 -0
  58. data/test/dummy/public/favicon.ico +0 -0
  59. data/test/dummy/test/fixtures/projects.yml +7 -0
  60. data/test/dummy/test/fixtures/tasks.yml +14 -0
  61. data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  62. data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  63. data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  64. data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  65. data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  66. data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  67. data/test/functional/auto_present_instance_vars_test.rb +34 -0
  68. data/test/test_helper.rb +11 -0
  69. metadata +187 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e3d56d88e59a4a4a44668eea58dc7cb5261cc47e
4
+ data.tar.gz: 3f9cb8fb4ba274780263cc39808f6f691b5d9f28
5
+ SHA512:
6
+ metadata.gz: d9d39a5e2c79ef1af3f448f843b0446d289f22e4668986c1d6047341e7f3b464ebca8d578749c8162490ff9d39a3855d1226a609808941943673628432b419b8
7
+ data.tar.gz: e4724857836cc87dc0668d3fdb2b38619fa077974c93836513f8f9724f4a419529a2509c514326ae27123c2d5a37efb0ef086fd00b30a482ab2a0f3b7656b7ec
@@ -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.
@@ -0,0 +1,51 @@
1
+ # AutoPresenter
2
+
3
+ [![Build Status](https://secure.travis-ci.org/afcapel/auto_presenter.png)](http://travis-ci.org/afcapel/auto_presenter)
4
+ [![Code Climate](https://codeclimate.com/github/afcapel/auto_presenter.png)](https://codeclimate.com/github/afcapel/auto_presenter)
5
+
6
+ AutoPresenter uses convention over configuration to remove the bolierplate code to use presenters in your rails app. That allows you to cleanly remove the presentation logic from your controllers.
7
+
8
+ ## Usage
9
+
10
+ Let's say you have a controller:
11
+
12
+ ```ruby
13
+ class ProjectsController < ApplicationController
14
+
15
+ def show
16
+ @project = Project.find(params[:id])
17
+
18
+ @completed_tasks = @project.tasks.completed
19
+ @uncompleted_tasks = @project.tasks.uncompleted
20
+ end
21
+ end
22
+ ```
23
+
24
+ To decorate `@completed_tasks` just create a presenter in `app/presenters/projects/completed_tasks_presenter.rb`. If you want to decorate any `Task` instance variable in your views just create a `TaskPresenter` in `app/presenters/task_presenter.rb`. There is no need to change your controller code.
25
+
26
+
27
+ ### Presenters
28
+
29
+ Autopresenter doesn't ship with any base presenter class you can inherit from. A presenter can be any object that accepts the decorated object in the initializer and adds presentation methods to it. The ruby standard library is `SimpleDelegator` usually a good and simple option to implement your delegators. Drapper decorators work well too.
30
+
31
+ ```ruby
32
+ class TaskPresenter < SimpleDelegator
33
+
34
+ # This method will be added to Task objects in the views.
35
+ def status
36
+ completed_at.present? ? 'Completed' : 'Uncompleted'
37
+ end
38
+ end
39
+ ```
40
+
41
+ ## Installation
42
+
43
+ Add AutoPresenter to your Gemfile
44
+
45
+ ```ruby
46
+ gem 'auto_presenter'
47
+ ```
48
+
49
+ ## License
50
+
51
+ Autopresenter is released under the [MIT License](http://www.opensource.org/licenses/MIT).
@@ -0,0 +1,29 @@
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 = 'AutoPresenter'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ Bundler::GemHelper.install_tasks
18
+
19
+ require 'rake/testtask'
20
+
21
+ Rake::TestTask.new(:test) do |t|
22
+ t.libs << 'lib'
23
+ t.libs << 'test'
24
+ t.pattern = 'test/**/*_test.rb'
25
+ t.verbose = false
26
+ end
27
+
28
+
29
+ task default: :test
@@ -0,0 +1,49 @@
1
+ require_relative 'auto_presenter/relation_presenter'
2
+
3
+ module AutoPresenter
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ define_callbacks :render
8
+ set_callback :render, :before, :auto_present_instance_vars
9
+ end
10
+
11
+ private
12
+
13
+ def render(*args, &block)
14
+ run_callbacks(:render) { super }
15
+ end
16
+
17
+ def auto_present_instance_vars
18
+ vars_to_present = instance_variables.collect(&:to_s).reject do |var_name|
19
+ var_name.starts_with?('@_')
20
+ end
21
+
22
+ vars_to_present.each { |instance_var_name| auto_present(instance_var_name) }
23
+ end
24
+
25
+ def auto_present(instance_var_name)
26
+ var = instance_variable_get(instance_var_name)
27
+ var_name = instance_var_name[1..-1] # without the @
28
+
29
+ presenter = auto_presenter_for(var_name, var)
30
+
31
+ if presenter
32
+ presented_object = presenter.new(var)
33
+ instance_variable_set(instance_var_name, presented_object)
34
+ end
35
+ end
36
+
37
+ def auto_presenter_for(var_name, var)
38
+ controller_presenter = "#{params[:controller]}/#{var_name}_presenter".camelize.safe_constantize
39
+
40
+ return controller_presenter if controller_presenter
41
+
42
+ if var.is_a?(ActiveRecord::Relation)
43
+ RelationPresenter
44
+ else
45
+ class_name = var.class.name
46
+ "#{class_name}Presenter".safe_constantize
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ require "delegate"
2
+
3
+ module AutoPresenter
4
+ class RelationPresenter < SimpleDelegator
5
+
6
+ delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to_ary, to: :to_a
7
+
8
+ def initialize(object)
9
+ __setobj__(object)
10
+
11
+ name = object.klass.name
12
+ @_presenter = "#{name}Presenter".safe_constantize
13
+
14
+ present_records if loaded?
15
+ end
16
+
17
+ def to_a
18
+ if @_presented || !@_presenter
19
+ __getobj__.to_a
20
+ else
21
+ present_records
22
+ end
23
+ end
24
+
25
+ def present_records
26
+ records = __getobj__.to_a.collect! { |record| @_presenter.new(record) }
27
+ @_presented = true
28
+ records
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module AutoPresenter
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ == README
2
+
3
+ This README would normally document whatever steps are necessary to get the
4
+ application up and running.
5
+
6
+ Things you may want to cover:
7
+
8
+ * Ruby version
9
+
10
+ * System dependencies
11
+
12
+ * Configuration
13
+
14
+ * Database creation
15
+
16
+ * Database initialization
17
+
18
+ * How to run the test suite
19
+
20
+ * Services (job queues, cache servers, search engines, etc.)
21
+
22
+ * Deployment instructions
23
+
24
+ * ...
25
+
26
+
27
+ Please feel free to use a different markup language if you do not plan to run
28
+ <tt>rake doc:app</tt>.
@@ -0,0 +1,6 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ Rails.application.load_tasks
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ include AutoPresenter
3
+ end
@@ -0,0 +1,64 @@
1
+ class ProjectsController < ApplicationController
2
+ before_filter :set_project, only: [:show, :edit, :update, :destroy]
3
+
4
+ # GET /projects
5
+ def index
6
+ @projects = Project.all
7
+ end
8
+
9
+ # GET /projects/1
10
+ def show
11
+ @tasks = @project.tasks
12
+
13
+ @new_task = @project.tasks.build
14
+
15
+ @completed_tasks = @project.tasks.completed
16
+ @uncompleted_tasks = @project.tasks.uncompleted
17
+ end
18
+
19
+ # GET /projects/new
20
+ def new
21
+ @project = Project.new
22
+ end
23
+
24
+ # GET /projects/1/edit
25
+ def edit
26
+ end
27
+
28
+ # POST /projects
29
+ def create
30
+ @project = Project.new(project_params)
31
+
32
+ if @project.save
33
+ redirect_to @project, notice: 'Project was successfully created.'
34
+ else
35
+ render :new
36
+ end
37
+ end
38
+
39
+ # PATCH/PUT /projects/1
40
+ def update
41
+ if @project.update(project_params)
42
+ redirect_to @project, notice: 'Project was successfully updated.'
43
+ else
44
+ render :edit
45
+ end
46
+ end
47
+
48
+ # DELETE /projects/1
49
+ def destroy
50
+ @project.destroy
51
+ redirect_to projects_url, notice: 'Project was successfully destroyed.'
52
+ end
53
+
54
+ private
55
+ # Use callbacks to share common setup or constraints between actions.
56
+ def set_project
57
+ @project = Project.find(params[:id])
58
+ end
59
+
60
+ # Only allow a trusted parameter "white list" through.
61
+ def project_params
62
+ params.require(:project).permit(:name)
63
+ end
64
+ end
@@ -0,0 +1,43 @@
1
+ class TasksController < ApplicationController
2
+ before_filter :set_project
3
+ before_filter :set_task, only: [:show, :edit, :update, :destroy]
4
+
5
+ # POST /tasks
6
+ def create
7
+ @task = @project.tasks.new(task_params)
8
+
9
+ if @task.save
10
+ redirect_to @project, notice: 'Task was successfully created.'
11
+ else
12
+ render :new
13
+ end
14
+ end
15
+
16
+ def update
17
+ if @task.update(task_params)
18
+ redirect_to @project, notice: 'Task was successfully updated.'
19
+ else
20
+ render :edit
21
+ end
22
+ end
23
+
24
+ # DELETE /tasks/1
25
+ def destroy
26
+ @task.destroy
27
+ redirect_to tasks_url, notice: 'Task was successfully destroyed.'
28
+ end
29
+
30
+ private
31
+
32
+ def set_project
33
+ @project = Project.find(params[:project_id])
34
+ end
35
+
36
+ def set_task
37
+ @task = @project.tasks.find(params[:id])
38
+ end
39
+
40
+ def task_params
41
+ params.require(:task).permit(:name, :completed_at)
42
+ end
43
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module ProjectsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module TasksHelper
2
+ end
@@ -0,0 +1,3 @@
1
+ class Project < ActiveRecord::Base
2
+ has_many :tasks
3
+ end
@@ -0,0 +1,10 @@
1
+ class Task < ActiveRecord::Base
2
+ belongs_to :project
3
+
4
+ scope :completed, -> { where('`tasks`.`completed_at` IS NOT NULL') }
5
+ scope :uncompleted, -> { where('`tasks`.`completed_at` IS NULL') }
6
+
7
+ def status
8
+ completed_at.present? ? 'Completed' : 'Uncompleted'
9
+ end
10
+ end
@@ -0,0 +1,2 @@
1
+ class ProjectPresenter < SimpleDelegator
2
+ end
@@ -0,0 +1,2 @@
1
+ class Projects::CompletedTasksPresenter < SimpleDelegator
2
+ end
@@ -0,0 +1,2 @@
1
+ class Projects::ProjectsPresenter < SimpleDelegator
2
+ end
@@ -0,0 +1,6 @@
1
+ class TaskPresenter < DelegateClass(Task)
2
+
3
+ def status
4
+ completed_at.present? ? 'Completed' : 'Uncompleted'
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %>
6
+ <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
7
+ <%= csrf_meta_tags %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>