diff --git a/.gitignore b/.gitignore index 050c9d9..d548e5f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ /log/* !/log/.keep /tmp +*.swp diff --git a/app/controllers/junior_stories_controller.rb b/app/controllers/junior_stories_controller.rb index 7ce088b..3ee1128 100644 --- a/app/controllers/junior_stories_controller.rb +++ b/app/controllers/junior_stories_controller.rb @@ -1,11 +1,17 @@ class JuniorStoriesController < ApplicationController def index - @junior_stories = JuniorStory.all + @junior_stories = JuniorStory. + filter(allowed_params(params)) + + @fields = fields + @csv_params = allowed_params(params).merge({ format: 'csv' }) + + @filtered = params_set? respond_to do |format| format.html - format.csv { send_data @junior_stories.to_csv, type: 'application/csv' } + format.csv { send_data @junior_stories.to_csv, type: 'application/csv', filename: 'junior_stories.csv' } end end @@ -17,7 +23,7 @@ def show end def create - @junior_story = JuniorStory.new(junior_story_params) + @junior_story = JuniorStory.new(allowed_params(required_params)) if @junior_story.save redirect_to junior_stories_path else @@ -26,11 +32,50 @@ def create end private - def junior_story_params - params.require(:junior_story).permit(:job, :happy_in_job, :happy_info, + def required_params + params.require(:junior_story) + end + + def allowed_params(params) + params.permit(:job, :happy_in_job, :happy_info, :gender, :city, :country, :days_per_week, :salary, :currency, :technology, :focus, :age, :years_working_in_total, :years_working_at_job, :education, :first_job, :remote, :tech_team_size, :company_size, :company_age, :person_of_colour, :other, :publishing_consent, :freelancer, :person_with_disability) end + + # TODO: shouldn't hard code this, but I like having demo search terms in the list + def fields + { + job: "junior developer", + happy_in_job: "yes", + happy_info: "It's ok", + gender: "female", + city: "Berlin", + country: "DE", + days_per_week: "5", + salary: "15000", + currency: "€", + technology: "RoR", + focus: "backend", + age: 30, + years_working_total: "less than 1 year", + years_working_at_job: "less than 1 year", + education: "self taught", + first_job: "no", + remote: "no", + tech_team_size: "5 - 10 people", + company_size: "less than 10 people", + company_age: 5, + person_of_colour: false, + other: "Thanks", + freelancer: "f" + } + end + + def params_set? + values = allowed_params(params).values + values.reject { |value| value.blank? || value.empty? || value.nil? } + !values.empty? + end end diff --git a/app/models/concerns/filterable.rb b/app/models/concerns/filterable.rb new file mode 100644 index 0000000..7e2d371 --- /dev/null +++ b/app/models/concerns/filterable.rb @@ -0,0 +1,15 @@ +module Filterable + extend ActiveSupport::Concern + + module ClassMethods + def filter(params) + results = self.all + params.each do |key, value| + if results.column_names.include? key + results = results.where(key => value) if value.present? + end + end + results + end + end +end diff --git a/app/models/junior_story.rb b/app/models/junior_story.rb index 7994227..4a48376 100644 --- a/app/models/junior_story.rb +++ b/app/models/junior_story.rb @@ -1,6 +1,7 @@ require 'csv' class JuniorStory < ApplicationRecord + include Filterable validates :salary, presence: true validates :currency, presence: true diff --git a/app/views/junior_stories/index.html.erb b/app/views/junior_stories/index.html.erb index d76e5ca..1ad0ec7 100644 --- a/app/views/junior_stories/index.html.erb +++ b/app/views/junior_stories/index.html.erb @@ -4,7 +4,43 @@

Junior Stories:

- <%= link_to "Download as CSV", junior_stories_path(format: "csv"), class: 'btn btn-info' %> + <%= link_to "Download as CSV", junior_stories_path(@csv_params), class: 'btn btn-info' %> + + + <% if @filtered %> + <%= link_to "Reset filters", junior_stories_path, class: 'btn btn-info' %> + <% end %> + +
<% @junior_stories.each do |j| %> diff --git a/spec/controllers/junior_story_controller_spec.rb b/spec/controllers/junior_story_controller_spec.rb new file mode 100644 index 0000000..1cb67a9 --- /dev/null +++ b/spec/controllers/junior_story_controller_spec.rb @@ -0,0 +1,81 @@ +require 'rails_helper' + +describe JuniorStoriesController do + describe 'GET index' do + context 'without filter params' do + it 'assigns @junior_stories' do + story = build :junior_story + story.save + get :index + expect(assigns(:junior_stories)).to eq([story]) + end + + it 'renders the index template' do + get :index + expect(response).to render_template('index') + end + + it 'does not render index, but instead responds with csv' do + get :index, format: 'csv' + expect(response).not_to render_template('index') + expect(response.content_type).to include 'application/csv' + end + end + + context 'with legal filter params' do + it 'returns only the filter appropriate junior_story' do + female_story = build :junior_story + female_story.gender = 'female' + female_story.save + + male_story = build :junior_story + male_story.gender = 'male' + male_story.save + + + get :index, { 'gender' => 'female' } + expect(assigns(:junior_stories)).to eq([female_story]) + end + + it 'renders the index template' do + get :index, { 'gender' => 'female' } + get :index + expect(response).to render_template('index') + end + + it 'does not render index, but instead responds with csv' do + get :index, { 'gender' => 'female', 'format' => 'csv' } + expect(response).not_to render_template('index') + expect(response.content_type).to include 'application/csv' + end + end + + context 'with illegal filter params' do + it 'ignores illegal filter params but respects legal filter params' do + female_story = build :junior_story + female_story.gender = 'female' + female_story.save + + male_story = build :junior_story + male_story.gender = 'male' + male_story.save + + + get :index, { 'makes_no_sense' => 'random', 'gender' => 'female' } + expect(assigns(:junior_stories)).to eq([female_story]) + end + + it 'renders the index template' do + get :index, { 'makes_no_sense' => 'random' } + get :index + expect(response).to render_template('index') + end + + it 'does not render index, but instead responds with csv' do + get :index, { 'makes_no_sense' => 'random', 'format' => 'csv' } + expect(response).not_to render_template('index') + expect(response.content_type).to include 'application/csv' + end + end + end +end diff --git a/spec/controllers/junior_stroy_controller_spec.rb b/spec/controllers/junior_stroy_controller_spec.rb deleted file mode 100644 index b9c3f84..0000000 --- a/spec/controllers/junior_stroy_controller_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'rails_helper' - -describe JuniorStoriesController do - describe 'GET index' do - it 'assigns @junior_stories' do - story = build :junior_story - story.save - get :index - expect(assigns(:junior_stories)).to eq([story]) - end - - it 'renders the index template' do - get :index - expect(response).to render_template('index') - end - - it 'does not render index, but instead responds with csv' do - get :index, format: 'csv' - expect(response).not_to render_template('index') - expect(response.content_type).to include 'application/csv' - end - end -end