recruiter 0.0.1 → 0.0.2

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 (100) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/Rakefile +2 -0
  4. data/app/assets/images/ruby.png +0 -0
  5. data/app/assets/images/ruby_72x72.png +0 -0
  6. data/app/assets/images/ruby_rotated.png +0 -0
  7. data/app/assets/images/ruby_worker.png +0 -0
  8. data/app/assets/javascripts/recruiter/application.js +3 -0
  9. data/app/assets/javascripts/recruiter/filters.js +35 -0
  10. data/app/assets/javascripts/recruiter/site.js +3 -0
  11. data/app/assets/stylesheets/recruiter/application.css.scss +7 -0
  12. data/app/assets/stylesheets/recruiter/foundation_and_overrides.scss +1251 -0
  13. data/app/assets/stylesheets/recruiter/gh-fork-ribbon.css +140 -0
  14. data/app/assets/stylesheets/recruiter/site.css.sass +116 -0
  15. data/app/assets/stylesheets/recruiter/variables.css.sass +6 -0
  16. data/app/controllers/recruiter/filters_controller.rb +14 -0
  17. data/app/controllers/recruiter/jobs_controller.rb +18 -0
  18. data/app/controllers/recruiter/omniauth_callbacks_controller.rb +45 -0
  19. data/app/controllers/recruiter/users/jobs_controller.rb +59 -0
  20. data/app/controllers/recruiter/users/user_controller.rb +8 -0
  21. data/app/controllers/recruiter_controller.rb +13 -0
  22. data/app/decorators/recruiter/job_decorator.rb +49 -0
  23. data/app/decorators/recruiter/user_decorator.rb +22 -0
  24. data/app/helpers/recruiter/crud_flash_messager_helper.rb +21 -0
  25. data/app/helpers/recruiter/form_helper.rb +29 -0
  26. data/app/helpers/recruiter/header_helper.rb +13 -0
  27. data/app/helpers/recruiter/icons_helper.rb +29 -0
  28. data/app/helpers/recruiter/links_helper.rb +59 -0
  29. data/app/helpers/recruiter/markdown_helper.rb +12 -0
  30. data/app/helpers/recruiter/oauth_providers_helper.rb +23 -0
  31. data/app/helpers/recruiter/show_helper.rb +29 -0
  32. data/app/models/recruiter/city.rb +9 -0
  33. data/app/models/recruiter/custom_devise_failure.rb +7 -0
  34. data/app/models/recruiter/filters.rb +44 -0
  35. data/app/models/recruiter/filters/city_filter.rb +21 -0
  36. data/app/models/recruiter/filters/job_filter.rb +21 -0
  37. data/app/models/recruiter/filters/state_filter.rb +17 -0
  38. data/app/models/recruiter/job.rb +34 -0
  39. data/app/{helpers/recruiter/application_helper.rb → models/recruiter/oauth.rb} +1 -1
  40. data/app/models/recruiter/oauth/base.rb +24 -0
  41. data/app/models/recruiter/oauth/facebook.rb +6 -0
  42. data/app/models/recruiter/oauth/github.rb +6 -0
  43. data/app/models/recruiter/oauth/google.rb +9 -0
  44. data/app/models/recruiter/state.rb +9 -0
  45. data/app/models/recruiter/tag.rb +6 -0
  46. data/app/models/recruiter/user.rb +11 -0
  47. data/app/views/devise/sessions/new.html.erb +8 -0
  48. data/app/views/kaminari/_first_page.html.erb +11 -0
  49. data/app/views/kaminari/_gap.html.erb +8 -0
  50. data/app/views/kaminari/_last_page.html.erb +11 -0
  51. data/app/views/kaminari/_next_page.html.erb +11 -0
  52. data/app/views/kaminari/_page.html.erb +12 -0
  53. data/app/views/kaminari/_paginator.html.erb +23 -0
  54. data/app/views/kaminari/_prev_page.html.erb +11 -0
  55. data/app/views/layouts/recruiter/application.html.erb +28 -10
  56. data/app/views/recruiter/_analytics.html.erb +10 -0
  57. data/app/views/recruiter/_filters.html.erb +17 -0
  58. data/app/views/recruiter/_flashes.html.erb +14 -0
  59. data/app/views/recruiter/_footer.html.erb +7 -0
  60. data/app/views/recruiter/_form_actions.html.erb +4 -0
  61. data/app/views/recruiter/_javascript.html.erb +10 -0
  62. data/app/views/recruiter/_login_button.html.erb +15 -0
  63. data/app/views/recruiter/_login_links.html.erb +7 -0
  64. data/app/views/recruiter/_login_status.html.erb +8 -0
  65. data/app/views/recruiter/_show_actions.html.erb +6 -0
  66. data/app/views/recruiter/_show_item.html.erb +8 -0
  67. data/app/views/recruiter/_tags.html.erb +6 -0
  68. data/app/views/recruiter/_top_menu.html.erb +28 -0
  69. data/app/views/recruiter/jobs/_job.html.erb +14 -0
  70. data/app/views/recruiter/jobs/index.html.erb +14 -0
  71. data/app/views/recruiter/jobs/show.html.erb +1 -0
  72. data/app/views/recruiter/users/jobs/_form.html.erb +30 -0
  73. data/app/views/recruiter/users/jobs/_job.html.erb +35 -0
  74. data/app/views/recruiter/users/jobs/edit.html.erb +3 -0
  75. data/app/views/recruiter/users/jobs/index.html.erb +24 -0
  76. data/app/views/recruiter/users/jobs/new.html.erb +3 -0
  77. data/app/views/recruiter/users/jobs/show.html.erb +4 -0
  78. data/config/initializers/devise.rb +272 -0
  79. data/config/initializers/simple_form.rb +145 -0
  80. data/config/routes.rb +19 -0
  81. data/config/spring.rb +1 -0
  82. data/db/migrate/20140617180316_create_recruiter_states.rb +12 -0
  83. data/db/migrate/20140617180934_create_recruiter_cities.rb +14 -0
  84. data/db/migrate/20140618164609_create_recruiter_users.rb +51 -0
  85. data/db/migrate/20140618165301_add_name_to_users.rb +5 -0
  86. data/db/migrate/20140618165802_create_recruiter_jobs.rb +14 -0
  87. data/db/migrate/20140618170815_create_recruiter_tags.rb +13 -0
  88. data/db/migrate/20140618170904_create_recruiter_jobs_tags.rb +10 -0
  89. data/lib/generators/templates/locales/devise.en.yml +59 -0
  90. data/lib/generators/templates/locales/devise.pt-BR.yml +60 -0
  91. data/lib/generators/templates/locales/en.yml +11 -0
  92. data/lib/generators/templates/locales/pt-BR.yml +237 -0
  93. data/lib/generators/templates/locales/recruiter.pt-BR.yml +78 -0
  94. data/lib/generators/templates/locales/simple_form.en.yml +26 -0
  95. data/lib/recruiter.rb +12 -0
  96. data/lib/recruiter/engine.rb +31 -0
  97. data/lib/recruiter/version.rb +1 -1
  98. metadata +362 -11
  99. data/app/assets/stylesheets/recruiter/application.css +0 -15
  100. data/app/controllers/recruiter/application_controller.rb +0 -4
@@ -0,0 +1,22 @@
1
+ module Recruiter
2
+ class UserDecorator < Draper::Decorator
3
+ delegate_all
4
+
5
+ def avatar(width = 50, height = 50)
6
+ url ||= image_url
7
+ url ||= gravatar_url
8
+ h.image_tag(url, width: width, height: height)
9
+ end
10
+
11
+ def image_url
12
+ @image_url ||= object.provider_data.deep_symbolize_keys[:info][:image]
13
+ end
14
+
15
+ def gravatar_url
16
+ if email
17
+ hash = Digest::MD5.hexdigest(email)
18
+ "http://www.gravatar.com/avatar/#{hash}"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,21 @@
1
+ module Recruiter
2
+ module CrudFlashMessagerHelper
3
+ def crud_flash(result, &block)
4
+ unless request.xhr?
5
+ result ? set_crud_success_flash : set_crud_error_flash
6
+ yield if result && block_given?
7
+ end
8
+ result
9
+ end
10
+
11
+ def set_crud_success_flash
12
+ default = t("recruiter.messages.crud.#{params[:action]}.success")
13
+ flash[:notice] = t('.success', default: default)
14
+ end
15
+
16
+ def set_crud_error_flash
17
+ default = t("recruiter.messages.crud.#{params[:action]}.error")
18
+ flash.now[:alert] = t('.success', default: default)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Recruiter
2
+ module FormHelper
3
+ def options_for_states
4
+ options_for(State)
5
+ end
6
+
7
+ def options_for_available_states
8
+ options_for(State.with_open_jobs)
9
+ end
10
+
11
+ def options_for_available_cities(state_id)
12
+ options_for City.with_open_jobs.where(state_id: state_id)
13
+ end
14
+
15
+ def options_for_cities(state_id = nil)
16
+ options_for City.where(state_id: state_id)
17
+ end
18
+
19
+ def options_for(scope)
20
+ scope.order(:name).select(:name, :id).map do |row|
21
+ [row.name, row.id]
22
+ end
23
+ end
24
+
25
+ def tags
26
+ Tag.order(:sequence)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ module Recruiter
2
+ module HeaderHelper
3
+ def title(title = nil)
4
+ if title
5
+ content_for(:title) { title }
6
+ else
7
+ parts = [content_for(:title)]
8
+ parts << 'Rails Jobs Brazil'
9
+ parts.compact.uniq.join(' :: ')
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ # http://zurb.com/playground/foundation-icon-fonts-3
2
+
3
+ module Recruiter
4
+ module IconsHelper
5
+ def icon(name, klass = nil)
6
+ content_tag(:i, nil, class: "fi-#{name} #{klass}")
7
+ end
8
+
9
+ def new_icon(klass = nil)
10
+ icon(:plus, klass)
11
+ end
12
+
13
+ def mail_icon(klass = nil)
14
+ icon(:mail, klass)
15
+ end
16
+
17
+ def edit_icon(klass = nil)
18
+ icon('page-edit', klass)
19
+ end
20
+
21
+ def destroy_icon(klass = nil)
22
+ icon(:trash, klass)
23
+ end
24
+
25
+ def show_icon(klass = nil)
26
+ icon(:eye, klass)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,59 @@
1
+ module Recruiter
2
+ module LinksHelper
3
+ def button_link(url, classes = nil, options = {}, &block)
4
+ classes = [options[:class], 'button', classes].compact
5
+ options.merge! class: classes
6
+ link_to url, options, &block
7
+ end
8
+
9
+ def new_link(url, options = {})
10
+ options.reverse_merge!({ title: t('recruiter.links.new') })
11
+
12
+ link_to(url, options) do
13
+ [new_icon, t('recruiter.links.new')].join(" ").html_safe
14
+ end
15
+ end
16
+
17
+ def edit_link(url, options = {}, &block)
18
+ options.reverse_merge!({ title: t('recruiter.links.edit') })
19
+ button_link(url, 'warning tiny', options) do
20
+ edit_icon
21
+ end
22
+ end
23
+
24
+ def destroy_link(url, options = { }, &block)
25
+ options.reverse_merge!({
26
+ method: :delete,
27
+ data: { confirm: t('recruiter.messages.confirm_destroy')},
28
+ title: t('recruiter.links.destroy'),
29
+ })
30
+ button_link(url, 'alert tiny', options) do
31
+ destroy_icon
32
+ end
33
+ end
34
+
35
+ def show_link(url, options = {}, &block)
36
+ options.reverse_merge!({ title: t('recruiter.links.show') })
37
+ button_link(url, 'secondary tiny', options) do
38
+ show_icon
39
+ end
40
+ end
41
+
42
+ def back_link(url = { action: :index }, options = {}, &block)
43
+ button_link(url, 'warning', options) do
44
+ t('recruiter.links.back')
45
+ end
46
+ end
47
+
48
+ def cancel_link(url = { action: :index }, options = {}, &block)
49
+ button_link(url, 'alert', options) do
50
+ t('recruiter.links.cancel')
51
+ end
52
+ end
53
+
54
+ def submit_button
55
+ action = params[:action]
56
+ content_tag(:button, t("recruiter.submit.#{action}"), class: 'success')
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,12 @@
1
+ module Recruiter
2
+ module MarkdownHelper
3
+ def to_markdown(text)
4
+ renderer.render(text).html_safe
5
+ end
6
+
7
+ def renderer
8
+ @renderer ||= Redcarpet::Render::HTML.new(filter_html: true)
9
+ @md_renderer ||= Redcarpet::Markdown.new(@renderer)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,23 @@
1
+ module Recruiter
2
+ module OauthProvidersHelper
3
+ def available_oauth_providers
4
+ {
5
+ github: :github,
6
+ google: :google_oauth2,
7
+ facebook: :facebook,
8
+ }.select do |key, provider|
9
+ ENV["#{key.to_s.upcase}_KEY"]
10
+ end
11
+ end
12
+
13
+ def provider_icon(provider)
14
+ icon(provider_icon_class(provider))
15
+ end
16
+
17
+ def provider_icon_class(provider)
18
+ {
19
+ google_oauth2: 'social-google-plus',
20
+ }.fetch(provider.to_sym) { "social-#{provider}" }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ module Recruiter
2
+ module ShowHelper
3
+ def show_for(model, &block)
4
+ if block_given?
5
+ yield AttributeShower.new(model, self)
6
+ end
7
+ end
8
+
9
+ class AttributeShower
10
+ attr_reader :object, :helper
11
+
12
+ def initialize(object, helper)
13
+ @object = object
14
+ @helper = helper
15
+ end
16
+
17
+ def show(attribute)
18
+ render(
19
+ object.class.human_attribute_name(attribute),
20
+ object.send(attribute)
21
+ )
22
+ end
23
+
24
+ def render(label, value)
25
+ helper.render('application/show_item', label: label, value: value)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,9 @@
1
+ module Recruiter
2
+ class City < ActiveRecord::Base
3
+ delegate :to_s, to: :name
4
+ belongs_to :state
5
+ validates :name, presence: true, uniqueness: { case_sensitive: false, scope: :state_id }
6
+
7
+ scope :with_open_jobs, ->{ where(id: Job.open.select(:city_id).uniq) }
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Recruiter
2
+ class CustomDeviseFailure < Devise::FailureApp
3
+ def redirect_url
4
+ '/sign_in'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,44 @@
1
+ module Recruiter
2
+ module Filters
3
+ def self.filter(type, params = {})
4
+ filter_class(type).new(params).filter
5
+ end
6
+
7
+ def self.filter_class(type)
8
+ "Recruiter::Filters::#{type.to_s.classify}Filter".constantize
9
+ end
10
+
11
+ class Base
12
+ attr_reader :query
13
+
14
+ def self.filter(params = {})
15
+ new(params).filter
16
+ end
17
+
18
+ def initialize(params = {})
19
+ init_query
20
+
21
+ params.each do |key, values|
22
+ method = "with_#{key}"
23
+
24
+ if respond_to?(method)
25
+ send(method, *values)
26
+ end
27
+ end
28
+ end
29
+
30
+ def init_query
31
+ end
32
+
33
+ def filter
34
+ query
35
+ end
36
+
37
+ def merge(scope = nil, &block)
38
+ @query = query.merge(yield) if block_given?
39
+ @query = query.merge(scope) if scope
40
+ self
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ module Recruiter
2
+ module Filters
3
+ class CityFilter < Base
4
+ def init_query
5
+ @query = City.order('name')
6
+ end
7
+
8
+ def with_jobs(*args)
9
+ merge(query.where(id: Job.select(:city_id).uniq))
10
+ end
11
+
12
+ def with_open_jobs(*args)
13
+ merge(City.with_open_jobs)
14
+ end
15
+
16
+ def with_state_id(id)
17
+ merge(query.where(state_id: id))
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Recruiter
2
+ module Filters
3
+ class JobFilter < Base
4
+ def init_query
5
+ @query = Job.joins(city: :state).includes(city: :state)
6
+ end
7
+
8
+ def with_open_status(*args)
9
+ merge(Job.open)
10
+ end
11
+
12
+ def with_city_id(id)
13
+ merge { query.where(city_id: id) }
14
+ end
15
+
16
+ def with_state_id(id)
17
+ merge { query.where(recruiter_cities: { state_id: id }) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Recruiter
2
+ module Filters
3
+ class StateFilter < Base
4
+ def init_query
5
+ @query = State.order('name')
6
+ end
7
+
8
+ def with_jobs(*args)
9
+ merge(query.where(id: Job.joins(city: :state).select(:state_id).uniq))
10
+ end
11
+
12
+ def with_open_jobs(*args)
13
+ merge(State.with_open_jobs)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ module Recruiter
2
+ class Job < ActiveRecord::Base
3
+ belongs_to :user
4
+ belongs_to :city
5
+ has_and_belongs_to_many :tags, class_name: 'Recruiter::Tag'
6
+
7
+ validates :user, presence: true
8
+ validates :city, presence: true
9
+ validates :title, presence: true
10
+ validates :description, presence: true
11
+ validates :how_to_apply, presence: true
12
+
13
+ default_scope ->{ order('recruiter_jobs.created_at DESC') }
14
+ scope :open, ->{ where(open: true) }
15
+
16
+ def to_param
17
+ "#{id}-#{title.parameterize}"
18
+ end
19
+
20
+ # form helper
21
+ def state_id=(value)
22
+ @state_id = value
23
+ end
24
+
25
+ # form helper
26
+ def state_id
27
+ if @state_id.present?
28
+ @state_id.to_i
29
+ elsif city.present?
30
+ city.state_id
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,4 +1,4 @@
1
1
  module Recruiter
2
- module ApplicationHelper
2
+ module Oauth
3
3
  end
4
4
  end
@@ -0,0 +1,24 @@
1
+ module Recruiter
2
+ module Oauth
3
+ class Base
4
+ def self.provider_key
5
+ to_s.underscore.split('/').last.to_sym
6
+ end
7
+
8
+ def self.find_or_build_user(params)
9
+ user = User.where(uid: params[:uid], provider: provider_key).first
10
+
11
+ unless user
12
+ user = User.new
13
+ user.uid = params[:uid]
14
+ user.provider = provider_key
15
+ end
16
+
17
+ user.provider_data = params
18
+ user.email = params[:info][:email]
19
+ user.name = params[:info][:name]
20
+ user
21
+ end
22
+ end
23
+ end
24
+ end