kitestrings 1.0.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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +38 -0
  7. data/Rakefile +10 -0
  8. data/kitestrings.gemspec +28 -0
  9. data/lib/array_validator.rb +22 -0
  10. data/lib/async.rb +26 -0
  11. data/lib/form_object.rb +96 -0
  12. data/lib/generators/kitestrings/install_generator.rb +41 -0
  13. data/lib/generators/kitestrings/messages_generator.rb +11 -0
  14. data/lib/generators/kitestrings/templates/message.rb.erb +56 -0
  15. data/lib/generators/templates/deploy.rb +136 -0
  16. data/lib/generators/templates/deploy/integ.rb +21 -0
  17. data/lib/generators/templates/deploy/production.rb +26 -0
  18. data/lib/generators/templates/deploy/uat.rb +23 -0
  19. data/lib/generators/templates/haml/scaffold/_form.html.haml +17 -0
  20. data/lib/generators/templates/haml/scaffold/edit.html.haml +6 -0
  21. data/lib/generators/templates/haml/scaffold/index.html.haml +27 -0
  22. data/lib/generators/templates/haml/scaffold/new.html.haml +6 -0
  23. data/lib/generators/templates/haml/scaffold/show.html.haml +10 -0
  24. data/lib/generators/templates/rails/scaffold_controller/controller.rb +62 -0
  25. data/lib/generators/templates/rspec/helper/helper_spec.rb +17 -0
  26. data/lib/generators/templates/rspec/integration/request.rb +4 -0
  27. data/lib/generators/templates/rspec/model/model_spec.rb +14 -0
  28. data/lib/generators/templates/rspec/scaffold/controller_spec.rb +131 -0
  29. data/lib/generators/templates/rspec/scaffold/routing_spec.rb +18 -0
  30. data/lib/generators/templates/spec_ext/my_ip_spec.rb +7 -0
  31. data/lib/generators/templates/spec_ext/spec_helper_ext.rb +37 -0
  32. data/lib/generators/templates/views/application/_navigation.html.haml +0 -0
  33. data/lib/generators/templates/views/layouts/application.html.haml +23 -0
  34. data/lib/kitestrings.rb +6 -0
  35. data/lib/kitestrings/railtie.rb +15 -0
  36. data/lib/kitestrings/version.rb +3 -0
  37. data/lib/page_and_sort_helper.rb +99 -0
  38. data/lib/size_validator.rb +22 -0
  39. data/lib/tasks/test_prepare_after_migrate.rake +11 -0
  40. data/lib/uniqueness_without_deleted_validator.rb +7 -0
  41. data/spec/lib/array_validator_spec.rb +40 -0
  42. data/spec/lib/async_spec.rb +49 -0
  43. data/spec/lib/generators/kitestrings/install_generator_spec.rb +53 -0
  44. data/spec/lib/generators/kitestrings/messages_generator_spec.rb +19 -0
  45. data/spec/lib/page_and_sort_helper_spec.rb +96 -0
  46. data/spec/lib/size_validator_spec.rb +40 -0
  47. data/spec/spec_helper.rb +17 -0
  48. metadata +181 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c0cfbc92932ce23470326d07836d6ef8ba8d24f6
4
+ data.tar.gz: a2c6b9b841e88fd63910f46bd36f80b7a25a3c3e
5
+ SHA512:
6
+ metadata.gz: afa6ba0918b66edd5d24c2ab9457f0548f95cb842049473cc1413b9d18780be556782a5b0d0c3ca2659a85b1bf74adf6b79af830bcfb044b2f94edf0cfd47237
7
+ data.tar.gz: b4e6825be0f105315cb4108b2259fcc02b2adafc753be9c859ed0445094269185767cd8c1cd0d757625ce729ce9efce0128b523cc3d3bf5eeffc44f5f8ed8cf0
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kitestrings.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 ridget
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # Kitestrings
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'kitestrings'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install kitestrings
18
+
19
+ Once installed run
20
+
21
+ rails g kitestrings:install
22
+
23
+ If installed using our template file, this will already be done for you.
24
+
25
+ ## Contains
26
+
27
+ Our scaffold templates (views, controlller)
28
+
29
+ A rake task which will run `db:test:prepare` after you run a migration and `db:fixtures:load` so your selections are properly
30
+ loaded in the test db.
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it ( https://github.com/[my-github-username]/kitestrings/fork )
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create a new Pull Request
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc "Run the specs."
6
+ RSpec::Core::RakeTask.new do |t|
7
+ t.pattern = "spec/**/*_spec.rb"
8
+ end
9
+
10
+ task :default => [:spec]
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kitestrings/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kitestrings"
8
+ spec.version = Kitestrings::VERSION
9
+ spec.authors = ["ridget"]
10
+ spec.email = ["tom.ridge@tworedkites.com"]
11
+ spec.summary = %q{For all the 2rk goodness}
12
+ spec.description = %q{}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "rails", ">= 3.2"
22
+ spec.add_runtime_dependency "activemodel", ">= 3.2"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.6"
25
+ spec.add_development_dependency "rake"
26
+ spec.add_development_dependency "rspec", "~> 2.14"
27
+ spec.add_development_dependency 'generator_spec'
28
+ end
@@ -0,0 +1,22 @@
1
+ # A validator to validate the length of an array. Only works on values that are arrays. (Not relationships in Rails 4)
2
+ class ArrayValidator < ActiveModel::EachValidator
3
+ # Validate the value is an Array and optionally that the number of items in it is at least a minimum or at most a
4
+ # maximum.
5
+ #
6
+ # Example:
7
+ # validates :address_states, array: {min: 1, min_message: "must have at least 1 State selected"},
8
+ #
9
+ def validate_each(record, attribute, value)
10
+ if value.is_a? Array
11
+ if options[:min].present? && value.size < options[:min]
12
+ record.errors.add attribute, options[:min_message] || "must have at least #{options[:min]} #{'item'.pluralize(options[:min])}"
13
+ end
14
+
15
+ if options[:max].present? && value.size > options[:max]
16
+ record.errors.add attribute, options[:max_message] || "must have at most #{options[:max]} #{'item'.pluralize(options[:max])}"
17
+ end
18
+ else
19
+ record.errors.add attribute, "must be an array"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ require 'active_support'
2
+
3
+ # a module for executing code asynchronously in another thread. This is disabled
4
+ module Async
5
+ mattr_accessor :enabled
6
+
7
+ # Execute the given block in another thread, but only in production. During development, the block executes
8
+ # on the current thread
9
+ # @return [Thread]
10
+ def async
11
+ raise "A block must be provided" unless block_given?
12
+ if Async.enabled
13
+ Thread.new do
14
+ # ensure that this thread uses a new connection to the database and returns it to the pool when done.
15
+ ActiveRecord::Base.connection_pool.with_connection do
16
+ yield
17
+ end
18
+ end
19
+ else
20
+ yield
21
+ Thread.current
22
+ end
23
+ end
24
+ end
25
+
26
+ Async.enabled = false
@@ -0,0 +1,96 @@
1
+ # This module is to help with using Form Objects that are backed by ActiveRecord resources. The goal
2
+ # is to make a from object act like the underlying model class, but with its own set of validations.
3
+ #
4
+ # Note that saving the form object requires validations in the form object to pass *AND* the validations
5
+ # in the underlying model object. Validation errors in the underlying model object will be included in
6
+ # the errors of the form object.
7
+ module FormObject
8
+ extend ActiveSupport::Concern
9
+ include ActiveModel::Model
10
+ include ActiveRecord::AttributeAssignment
11
+ include ActiveRecord::Persistence
12
+
13
+ module ClassMethods
14
+ # Set up the Form Object class to be a form object for a given model.
15
+ #
16
+ # Example:
17
+ #
18
+ # class NewWorkflow
19
+ # include FormObject
20
+ # form_object_for :workflow, :fields => [:name], :class => MyOtherClass
21
+ # ...
22
+ #
23
+ # This creates a :workflow attr method and delegates methods to it for use with form_for.
24
+ def form_object_for(resource_name, options={})
25
+ # create an attribute for the underlying resource name, (eg :workflow) and make an alias method "resource"
26
+ # for the attr reader
27
+ attr resource_name
28
+ alias_method :resource, resource_name
29
+
30
+ # create a class attribute with the model name of the underlying model name so that polymorphic_url will
31
+ # see the form object as if it were an instance of the underlying model object.
32
+ class_attribute :model_name
33
+ klass = options[:class] || resource_name.to_s
34
+ klass = klass.camelize.constantize unless klass.is_a?(Class)
35
+ self.model_name = klass.model_name
36
+
37
+ # delegate the following methods to the underlying model object, also helps polymorphic_url do the right thing
38
+ # for `form_for @form_object`
39
+ methods_to_delegate = [:id, :persisted?, :to_param]
40
+ if options[:fields]
41
+ options[:fields].each do |field|
42
+ methods_to_delegate << "#{field}".to_sym
43
+ methods_to_delegate << "#{field}=".to_sym
44
+ end
45
+ end
46
+ delegate *methods_to_delegate, :to => resource_name
47
+ include DelegateEverything if options[:delegate_everything]
48
+
49
+ # create a default initializer which will set the resource when a single parameter is passed in.
50
+ define_method :initialize do |object=nil|
51
+ instance_variable_set("@#{resource_name}", object)
52
+ end
53
+ end
54
+ end
55
+
56
+ # Validate the form object and if it's valid, call save on the underlying model object. If there are multiple models
57
+ # that need to be saved you will need to reimplement this method.
58
+ def save(*args)
59
+ if valid?
60
+ resource.save
61
+ end
62
+ end
63
+
64
+ # The form object is valid when its validations pass *AND* the underlying model validations pass. If there
65
+ # are errors in the underlying resource, those errors are copied into the errors object for this form object
66
+ # so that they exist in a single place (easy for the form to work with)
67
+ def valid?
68
+ result = [super, resource.valid?].all?
69
+
70
+ # include any errors in the resource object in the +errors+ for this form object. This is useful
71
+ # for uniqueness validation or existing validations in the model class so that they don't need
72
+ # to be duplicated in the form object. (And especially uniqueness validators can only be run in
73
+ # the ActiveRecord::Base model class.
74
+ unless result
75
+ resource.errors.each do |attr, error|
76
+ errors[attr] << error unless errors[attr].include?(error)
77
+ end
78
+ end
79
+
80
+ result
81
+ end
82
+
83
+ module DelegateEverything
84
+ def method_missing(method, *args, &block)
85
+ if resource.respond_to?(method)
86
+ resource.send(method, *args, &block)
87
+ else
88
+ super
89
+ end
90
+ end
91
+
92
+ def respond_to_missing?(method, include_all)
93
+ resource.respond_to?(method, include_all) || super
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,41 @@
1
+ require 'rails'
2
+ require 'rails/generators'
3
+
4
+ module Kitestrings
5
+ module Generators
6
+ class InstallGenerator < ::Rails::Generators::Base
7
+ source_root File.expand_path("../../templates", __FILE__)
8
+
9
+ desc "Copies 2rk relevant templates to the relevant directory"
10
+
11
+ def copy_deploy
12
+ copy_file "deploy.rb", "config/deploy.rb"
13
+ end
14
+
15
+ def copy_deploy_files
16
+ directory "deploy", "config/deploy"
17
+ end
18
+
19
+ def copy_haml_files
20
+ directory "haml", "lib/templates/haml"
21
+ end
22
+
23
+ def copy_scaffold_files
24
+ directory "rails", "lib/templates/rails"
25
+ end
26
+
27
+ def copy_rspec_files
28
+ directory "rspec", "lib/templates/rspec"
29
+ end
30
+
31
+ def copy_spec_ext
32
+ directory "spec_ext", "spec_ext"
33
+ end
34
+
35
+ def copy_app_view_files
36
+ copy_file "views/application/_navigation.html.haml", "app/views/application/_navigation.html.haml"
37
+ copy_file "views/layouts/application.html.haml", "app/views/layouts/application.html.haml"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,11 @@
1
+ module Kitestrings
2
+ module Generators
3
+ class MessagesGenerator < Rails::Generators::Base
4
+ source_root File.expand_path("../templates", __FILE__)
5
+
6
+ def setup_messages_model
7
+ template "message.rb.erb", "app/models/message.rb"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,56 @@
1
+ class Message < ActiveRecord::Base
2
+ include Async
3
+
4
+ DELIVERY_TIMEOUT = 5
5
+
6
+ <%- if Rails.version =~ /^3/ %>
7
+ attr_accessible :clicked_at, :link, :sent_at, :template, :user_id, :user, :options, :context, :subject
8
+
9
+ <% end %>
10
+ serialize :options
11
+
12
+ include Rails.application.routes_url_helpers
13
+
14
+ after_create :send_email
15
+
16
+ ## RELATIONSHIPS
17
+
18
+ belongs_to :context, polymorphic: true
19
+ belongs_to :user
20
+
21
+ ## VALIDATIONS
22
+
23
+ validates :user, presence: true
24
+
25
+ ## SCOPES
26
+
27
+ scope :latest, -> { order('created_at DESC') }
28
+
29
+ ## METHODS
30
+
31
+ def send_email
32
+ async do
33
+ Timeout.timeout DELIVERY_TIMEOUT do
34
+ mail.deliver
35
+
36
+ # always update the sent at, even if the email address is not on the whitelist to simulate what would happen
37
+ self.update_column(:sent_at, Time.now)
38
+ end
39
+ end
40
+ end
41
+
42
+ # prepare a mail object ready for delivery by email or display on the screen
43
+ def mail
44
+ @mail ||= MessageMailer.prepare_message(self, context)
45
+ end
46
+
47
+ # The "view" link. This is the link to the messages controller that marks the message
48
+ # as "clicked" and redirects to the actual link stored in the message record.
49
+ def view_link
50
+ message_url(self, :only_path => false)
51
+ end
52
+
53
+ def name
54
+ "Message ID: #{id}"
55
+ end
56
+ end
@@ -0,0 +1,136 @@
1
+ require 'bundler/capistrano'
2
+ require 'rvm/capistrano'
3
+ require 'capistrano/ext/multistage'
4
+ require 'airbrake/capistrano'
5
+
6
+ set :stages, %w(integ, uat, production)
7
+ set :default_stage, "integ"
8
+ set :application, 'pwi'
9
+ set :user, 'pwi'
10
+ set (:deploy_to) { "/home/#{user}/apps/#{rails_env}" }
11
+ set :deploy_via, :remote_cache
12
+ set :use_sudo, false
13
+ set :scm, 'git'
14
+ #set :repository, 'git@github.com:2rk/pwi.git'
15
+
16
+ set :ssl, false
17
+ # set :ssl_certificates_path, '/home/amt/ssl'
18
+ # set :ssl_certificates_name, 'amt'
19
+
20
+ set :mysql_password, YAML::load_file("config/database.yml.server")["production"]["password"]
21
+ set :bundle_flags, "--deployment"
22
+
23
+ namespace :deploy do
24
+
25
+ task :airbrake_test do
26
+ run "cd #{current_path}; RAILS_ENV=#{stage} bin/rake airbrake:test; true"
27
+ end
28
+
29
+ task :nginx_conf do
30
+ set :nginx_conf_file, "/opt/nginx/conf/servers/#{application}_#{stage}.conf"
31
+
32
+ ssl_conf = <<ssl_conf
33
+ ssl on;
34
+ ssl_certificate #{ssl_certificates_path}/#{ssl_certificates_name}.crt;
35
+ ssl_certificate_key #{ssl_certificates_path}/#{ssl_certificates_name}.key;
36
+
37
+ passenger_set_cgi_param HTTPS on;
38
+ passenger_set_cgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
39
+ passenger_set_cgi_param SSL_CLIENT_VERIFY $ssl_client_verify;
40
+
41
+ passenger_set_cgi_param HTTP_X_FORWARDED_PROTO https;
42
+ }
43
+
44
+ server {
45
+ listen 80;
46
+ server_name #{hostnames};
47
+ rewrite ^ https://#{hostnames}$request_uri? permanent;
48
+ ssl_conf
49
+
50
+ conf = <<conf
51
+ server {
52
+ listen #{ssl ? 443 : 80};
53
+ server_name #{user}.#{stage}.tworedkites.com #{hostnames};
54
+ root /home/#{user}/apps/#{stage}/current/public;
55
+ passenger_enabled on;
56
+ passenger_ruby /usr/local/rvm/bin/#{application}_ruby;
57
+ rack_env production;
58
+ client_max_body_size 10m;
59
+
60
+ #{ssl_conf}
61
+ }
62
+ conf
63
+
64
+ put(conf, nginx_conf_file)
65
+
66
+ run "sudo service nginx reload"
67
+ end
68
+
69
+
70
+ task :github_ssh_key do
71
+ run "ssh-keygen -t rsa -f ~/.ssh/id_rsa -P ''; ssh -oStrictHostKeyChecking=no git@github.com; cat .ssh/id_rsa.pub"
72
+ end
73
+
74
+ task :symlink_config do
75
+ run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
76
+ end
77
+ before "deploy:assets:precompile", "deploy:symlink_config"
78
+
79
+ task :create_shared_database_config do
80
+ run "mkdir -p #{shared_path}/config"
81
+ top.upload File.expand_path('../database.yml.server', __FILE__), "#{shared_path}/config/database.yml"
82
+ end
83
+
84
+
85
+ task :create_shared_rvmrc do
86
+ run "cp #{release_path}/.rvmrc.#{rails_env}.example #{release_path}/.rvmrc"
87
+ end
88
+
89
+ after "deploy:finalize_update", "deploy:create_shared_rvmrc"
90
+
91
+ task :create_database do
92
+ set :mysql_pass_arg, mysql_password.blank? ? '' : "-p#{mysql_password}"
93
+ run "mysql --user=root #{mysql_pass_arg} -e \"CREATE DATABASE IF NOT EXISTS #{application}_#{stage}\""
94
+ end
95
+
96
+ task :restart, :roles => :app, :except => { :no_release => true } do
97
+ run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
98
+ end
99
+ end
100
+
101
+ namespace :ruby_make do
102
+ desc "Run a task on a remote server."
103
+ # run like: cap staging rake:invoke task=a_certain_task
104
+ task :invoke do
105
+ run("cd #{deploy_to}/current; /usr/bin/env rake #{ENV['task']} RAILS_ENV=#{rails_env}")
106
+ end
107
+ end
108
+
109
+ # if you want to clean up old releases on each deploy uncomment this:
110
+ # after "deploy:restart", "deploy:cleanup"
111
+
112
+ # if you're still using the script/reaper helper you will need
113
+ # these http://github.com/rails/irs_process_scripts
114
+
115
+ # If you are using Passenger mod_rails uncomment this:
116
+ namespace :deploy do
117
+ task :start do ; end
118
+ task :stop do ; end
119
+ task :restart, :roles => :app, :except => { :no_release => true } do
120
+ run "#{try_sudo} touch #{File.join(current_path,'tmp','restart.txt')}"
121
+ end
122
+ desc "reload the database with seed data"
123
+ task :seed do
124
+ run "cd #{current_path}; bundle exec rake db:seed RAILS_ENV=#{rails_env}"
125
+ end
126
+ end
127
+
128
+ namespace :rvm do
129
+ task :trust_rvmrc do
130
+ run "rvm rvmrc trust #{release_path}"
131
+ end
132
+ end
133
+
134
+ after "deploy", "rvm:trust_rvmrc"
135
+ after 'deploy:setup', 'deploy:create_database', 'deploy:github_ssh_key', 'deploy:nginx_conf', 'deploy:create_shared_database_config'
136
+ after 'deploy:cold', 'deploy:airbrake_test'