From 26b6902af37a6e4763c1a6d95438e326359b9f64 Mon Sep 17 00:00:00 2001 From: James Mason Date: Sun, 12 Nov 2017 20:59:48 -0800 Subject: [PATCH 01/23] Explicity compress assets --- config/application.rb | 3 +++ config/environments/production.rb | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/config/application.rb b/config/application.rb index 4e3844ad..7e5e3a5d 100644 --- a/config/application.rb +++ b/config/application.rb @@ -60,6 +60,9 @@ module Osem # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0' + # Set cache headers + config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=31536000' } + config.active_job.queue_adapter = :delayed_job end end diff --git a/config/environments/production.rb b/config/environments/production.rb index 11a8c06b..2a9bf1f8 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -25,6 +25,10 @@ Osem::Application.configure do # Generate digests for assets URLs config.assets.digest = true + config.assets.css_compressor = :sass + config.assets.js_compressor = :uglifier + config.assets.gzip = true + # Defaults to nil and saved in location specified by config.assets.prefix # config.assets.manifest = YOUR_PATH From 32a6d698518aa125a14a63b3624b6a855bc05667 Mon Sep 17 00:00:00 2001 From: James Mason Date: Sun, 12 Nov 2017 21:06:01 -0800 Subject: [PATCH 02/23] Enable compression in Rack --- config.ru | 1 + 1 file changed, 1 insertion(+) diff --git a/config.ru b/config.ru index 988dac89..a0123600 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,5 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) +use Rack::Deflater run Osem::Application From e3b83e8ec14b89df94edba0916da9bf497ec6897 Mon Sep 17 00:00:00 2001 From: Marie-Elise Date: Sat, 13 Jan 2018 21:24:00 -0600 Subject: [PATCH 03/23] Hid create organization button from non-superadmin users. --- app/views/admin/organizations/index.html.haml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/views/admin/organizations/index.html.haml b/app/views/admin/organizations/index.html.haml index baf9bc80..7226d2a6 100644 --- a/app/views/admin/organizations/index.html.haml +++ b/app/views/admin/organizations/index.html.haml @@ -2,8 +2,9 @@ .col-md-12 .page-header %h1 Organizations - .btn-group.pull-right - = link_to 'Create Organization', new_admin_organization_path, class: 'btn btn-success pull-right' + - if can? :manage, :all + .btn-group.pull-right + = link_to 'Create Organization', new_admin_organization_path, class: 'btn btn-success pull-right' %p.text-muted Manage organizations in OSEM .row From 34af9b840b3b970a081fc74738d84cf4193dd0de Mon Sep 17 00:00:00 2001 From: Marie-Elise Date: Sat, 13 Jan 2018 22:40:42 -0600 Subject: [PATCH 04/23] Added condition to check for existing splashpage. Will redirect user if splashpage is not found. --- app/controllers/conferences_controller.rb | 58 ++++++++++++----------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index 4b01ca29..aaa0c278 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -20,36 +20,40 @@ class ConferencesController < ApplicationController authorize! :show, @conference # TODO: reduce the 10 queries performed here splashpage = @conference.splashpage - if splashpage.include_cfp - cfps = @conference.program.cfps - @call_for_events = cfps.find { |call| call.cfp_type == 'events' } - if @call_for_events.try(:open?) - @event_types = @conference.event_types.pluck(:title) - @track_names = @conference.confirmed_tracks.pluck(:name).sort + if !splashpage.present? + redirect_to admin_conference_splashpage_path(@conference.short_title) + else + if splashpage.include_cfp + cfps = @conference.program.cfps + @call_for_events = cfps.find { |call| call.cfp_type == 'events' } + if @call_for_events.try(:open?) + @event_types = @conference.event_types.pluck(:title) + @track_names = @conference.confirmed_tracks.pluck(:name).sort + end + @call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' } end - @call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' } - end - if splashpage.include_program - @highlights = @conference.highlighted_events.eager_load(:speakers) - if splashpage.include_tracks - @tracks = @conference.confirmed_tracks.eager_load( - :room - ).order('tracks.name') + if splashpage.include_program + @highlights = @conference.highlighted_events.eager_load(:speakers) + if splashpage.include_tracks + @tracks = @conference.confirmed_tracks.eager_load( + :room + ).order('tracks.name') + end + if splashpage.include_booths + @booths = @conference.confirmed_booths.order('title') + end end - if splashpage.include_booths - @booths = @conference.confirmed_booths.order('title') + if splashpage.include_registrations || splashpage.include_tickets + @tickets = @conference.tickets.order('price_cents') + end + if splashpage.include_lodgings + @lodgings = @conference.lodgings.order('name') + end + if splashpage.include_sponsors + @sponsorship_levels = @conference.sponsorship_levels.eager_load( + :sponsors + ).order('sponsorship_levels.position ASC', 'sponsors.name') end - end - if splashpage.include_registrations || splashpage.include_tickets - @tickets = @conference.tickets.order('price_cents') - end - if splashpage.include_lodgings - @lodgings = @conference.lodgings.order('name') - end - if splashpage.include_sponsors - @sponsorship_levels = @conference.sponsorship_levels.eager_load( - :sponsors - ).order('sponsorship_levels.position ASC', 'sponsors.name') end end From afff7e1c660b6362e7b591b81002d9ff001d78e4 Mon Sep 17 00:00:00 2001 From: Marie-Elise Date: Mon, 15 Jan 2018 22:23:38 -0600 Subject: [PATCH 05/23] Refactored condition to check if splashpage is present. --- app/controllers/conferences_controller.rb | 63 ++++++++++++----------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index aaa0c278..cb554f0c 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -20,41 +20,42 @@ class ConferencesController < ApplicationController authorize! :show, @conference # TODO: reduce the 10 queries performed here splashpage = @conference.splashpage - if !splashpage.present? - redirect_to admin_conference_splashpage_path(@conference.short_title) - else - if splashpage.include_cfp - cfps = @conference.program.cfps - @call_for_events = cfps.find { |call| call.cfp_type == 'events' } - if @call_for_events.try(:open?) - @event_types = @conference.event_types.pluck(:title) - @track_names = @conference.confirmed_tracks.pluck(:name).sort - end - @call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' } + + unless splashpage.present? + redirect_to admin_conference_splashpage_path(@conference.short_title) and return + end + + if splashpage.include_cfp + cfps = @conference.program.cfps + @call_for_events = cfps.find { |call| call.cfp_type == 'events' } + if @call_for_events.try(:open?) + @event_types = @conference.event_types.pluck(:title) + @track_names = @conference.confirmed_tracks.pluck(:name).sort end - if splashpage.include_program - @highlights = @conference.highlighted_events.eager_load(:speakers) - if splashpage.include_tracks - @tracks = @conference.confirmed_tracks.eager_load( - :room - ).order('tracks.name') - end - if splashpage.include_booths - @booths = @conference.confirmed_booths.order('title') - end + @call_for_tracks = cfps.find { |call| call.cfp_type == 'tracks' } + end + if splashpage.include_program + @highlights = @conference.highlighted_events.eager_load(:speakers) + if splashpage.include_tracks + @tracks = @conference.confirmed_tracks.eager_load( + :room + ).order('tracks.name') end - if splashpage.include_registrations || splashpage.include_tickets - @tickets = @conference.tickets.order('price_cents') - end - if splashpage.include_lodgings - @lodgings = @conference.lodgings.order('name') - end - if splashpage.include_sponsors - @sponsorship_levels = @conference.sponsorship_levels.eager_load( - :sponsors - ).order('sponsorship_levels.position ASC', 'sponsors.name') + if splashpage.include_booths + @booths = @conference.confirmed_booths.order('title') end end + if splashpage.include_registrations || splashpage.include_tickets + @tickets = @conference.tickets.order('price_cents') + end + if splashpage.include_lodgings + @lodgings = @conference.lodgings.order('name') + end + if splashpage.include_sponsors + @sponsorship_levels = @conference.sponsorship_levels.eager_load( + :sponsors + ).order('sponsorship_levels.position ASC', 'sponsors.name') + end end private From 5d816f934a94a69c721f58f69d3191847164c6f7 Mon Sep 17 00:00:00 2001 From: Marie-Elise Date: Tue, 16 Jan 2018 19:38:22 -0600 Subject: [PATCH 06/23] Corrected formatting errors. --- app/controllers/conferences_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index cb554f0c..5e907cea 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -22,7 +22,7 @@ class ConferencesController < ApplicationController splashpage = @conference.splashpage unless splashpage.present? - redirect_to admin_conference_splashpage_path(@conference.short_title) and return + redirect_to admin_conference_splashpage_path(@conference.short_title) && return end if splashpage.include_cfp From 86cab52f52cf72fa91d7815bba90e8274ce5c536 Mon Sep 17 00:00:00 2001 From: ViditChitkara Date: Sat, 23 Dec 2017 17:06:54 +0530 Subject: [PATCH 07/23] fixed ticket turnover bug closes #1918 --- app/models/ticket.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index b49cf1b9..fdac09bf 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -62,7 +62,7 @@ class Ticket < ApplicationRecord def tickets_turnover_total(id) tickets = TicketPurchase.where(ticket_id: id).paid - tickets.inject(0){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } + tickets.inject(Money.new(0,tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } end def tickets_sold From 0ec937e43e56fef8ccbae74472e2b52768ffbf21 Mon Sep 17 00:00:00 2001 From: ViditChitkara Date: Sat, 23 Dec 2017 18:34:26 +0530 Subject: [PATCH 08/23] fixed failing tests --- app/models/ticket.rb | 6 +++++- db/schema.rb | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index fdac09bf..d9723a2b 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -62,7 +62,11 @@ class Ticket < ApplicationRecord def tickets_turnover_total(id) tickets = TicketPurchase.where(ticket_id: id).paid - tickets.inject(Money.new(0,tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } + if tickets.nil? + tickets.inject(Money.new(0, tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } + else + Money.new(0, Ticket.find(id).price_currency) + end end def tickets_sold diff --git a/db/schema.rb b/db/schema.rb index ed33d5a3..48815a8a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -496,7 +496,7 @@ ActiveRecord::Schema.define(version: 20171201163628) do t.integer "user_id" t.integer "payment_id" t.integer "week" - t.float "amount_paid" + t.float "amount_paid", default: 0.0 end create_table "ticket_scannings", force: :cascade do |t| From 6d67e9c959ce3c030239b3dd642c733fad31e336 Mon Sep 17 00:00:00 2001 From: ViditChitkara Date: Sat, 23 Dec 2017 18:41:10 +0530 Subject: [PATCH 09/23] minor changes --- app/models/ticket.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index d9723a2b..19f2f2f4 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -62,7 +62,7 @@ class Ticket < ApplicationRecord def tickets_turnover_total(id) tickets = TicketPurchase.where(ticket_id: id).paid - if tickets.nil? + unless tickets. blank? tickets.inject(Money.new(0, tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } else Money.new(0, Ticket.find(id).price_currency) From 66a2777677284f7976f601bc46c7a9780b7779b0 Mon Sep 17 00:00:00 2001 From: ViditChitkara Date: Tue, 2 Jan 2018 19:29:28 +0530 Subject: [PATCH 10/23] changes for test faliures --- app/models/ticket.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/models/ticket.rb b/app/models/ticket.rb index 19f2f2f4..80e7f3e0 100644 --- a/app/models/ticket.rb +++ b/app/models/ticket.rb @@ -62,10 +62,10 @@ class Ticket < ApplicationRecord def tickets_turnover_total(id) tickets = TicketPurchase.where(ticket_id: id).paid - unless tickets. blank? - tickets.inject(Money.new(0, tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } - else + if tickets.blank? Money.new(0, Ticket.find(id).price_currency) + else + tickets.inject(Money.new(0, tickets.first.price_currency)){ |sum, ticket| sum + (ticket.amount_paid * ticket.quantity) } end end From ed21986cf1cb676af52715dc59cd83ac35933c1a Mon Sep 17 00:00:00 2001 From: AnkushMalik Date: Thu, 25 Jan 2018 09:09:18 +0530 Subject: [PATCH 11/23] Fix oauth btn alignment Use flex for alignment of btn grp Closes #1931 --- app/assets/stylesheets/osem.scss | 6 ++++++ app/views/devise/shared/_openid_links.html.haml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/osem.scss b/app/assets/stylesheets/osem.scss index bbcabc44..7d0d0519 100644 --- a/app/assets/stylesheets/osem.scss +++ b/app/assets/stylesheets/osem.scss @@ -115,3 +115,9 @@ p.comment-body { float: right; } } + +/* omniauth btn grp */ +#openid-btn-grp{ + display: flex; + justify-content: center; +} \ No newline at end of file diff --git a/app/views/devise/shared/_openid_links.html.haml b/app/views/devise/shared/_openid_links.html.haml index 8bcc96da..09c7a7ea 100644 --- a/app/views/devise/shared/_openid_links.html.haml +++ b/app/views/devise/shared/_openid_links.html.haml @@ -1,5 +1,5 @@ .text-center - .btn-group.btn-group-lg + .btn-group.btn-group-lg#openid-btn-grp - omniauth_configured.each do |provider| = link_to "user_#{provider}_omniauth_authorize".to_sym, class: "btn btn-success btn-lg", id: "omniauth-#{provider}", From 82d8629e43e76ef762622740dd7b73fc4bb40c4f Mon Sep 17 00:00:00 2001 From: James Mason Date: Wed, 17 Jan 2018 12:27:22 -0800 Subject: [PATCH 12/23] Fix social media section of splashpage Commit e1e0bdb4 inadvertently added a 2nd version of the partial. --- app/views/conferences/_social_media.haml | 3 +++ app/views/conferences/_social_media.html.haml | 21 ------------------- 2 files changed, 3 insertions(+), 21 deletions(-) delete mode 100644 app/views/conferences/_social_media.html.haml diff --git a/app/views/conferences/_social_media.haml b/app/views/conferences/_social_media.haml index 32cf1b16..28a87dbc 100644 --- a/app/views/conferences/_social_media.haml +++ b/app/views/conferences/_social_media.haml @@ -15,6 +15,9 @@ - unless contact.googleplus.blank? = link_to "#{ contact.googleplus }" do %i.fa.fa-google-plus-square.fa-4x + - unless contact.mastodon.blank? + = link_to "#{ contact.mastodon }" do + %i.fa.icon-mastodon.fa-4x - unless contact.email.blank? = mail_to "#{ contact.email }" do %i.fa.fa-envelope-o.fa-4x diff --git a/app/views/conferences/_social_media.html.haml b/app/views/conferences/_social_media.html.haml deleted file mode 100644 index 49216b6c..00000000 --- a/app/views/conferences/_social_media.html.haml +++ /dev/null @@ -1,21 +0,0 @@ -.container - .row - .col-md-12.text-center - - unless @conference.contact.facebook.blank? - = link_to "#{ @conference.contact.facebook }" do - %i.fa.fa-facebook-square.fa-4x - - unless @conference.contact.twitter.blank? - = link_to "#{ @conference.contact.twitter }" do - %i.fa.fa-twitter.fa-4x - - unless @conference.contact.instagram.blank? - = link_to "#{ @conference.contact.instagram }" do - %i.fa.fa-instagram.fa-4x - - unless @conference.contact.googleplus.blank? - = link_to "#{ @conference.contact.googleplus }" do - %i.fa.fa-google-plus-square.fa-4x - - unless @conference.contact.mastodon.blank? - = link_to "#{ @conference.contact.mastodon }" do - %i.fa.icon-mastodon.fa-4x - - unless @conference.contact.email.blank? - = mail_to "#{ @conference.contact.email }" do - %i.fa.fa-envelope-o.fa-4x From 63515cef5803b2882ec21b6bc557cbc574fdce00 Mon Sep 17 00:00:00 2001 From: James Mason Date: Wed, 17 Jan 2018 17:03:23 -0800 Subject: [PATCH 13/23] Change Conference#show to load sponsors Caching on sponsorship levels alone is not changing; as a bonus the sponsor modals are simplified a little. --- app/controllers/conferences_controller.rb | 1 + app/views/conferences/_sponsors.haml | 4 ++-- app/views/conferences/show.html.haml | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/conferences_controller.rb b/app/controllers/conferences_controller.rb index 5e907cea..1c9b37b3 100644 --- a/app/controllers/conferences_controller.rb +++ b/app/controllers/conferences_controller.rb @@ -55,6 +55,7 @@ class ConferencesController < ApplicationController @sponsorship_levels = @conference.sponsorship_levels.eager_load( :sponsors ).order('sponsorship_levels.position ASC', 'sponsors.name') + @sponsors = @conference.sponsors end end diff --git a/app/views/conferences/_sponsors.haml b/app/views/conferences/_sponsors.haml index 8f4d55c6..5d7bbaa9 100644 --- a/app/views/conferences/_sponsors.haml +++ b/app/views/conferences/_sponsors.haml @@ -2,7 +2,7 @@ %li %a.smoothscroll{ href: '#sponsors' } Sponsors -- cache [conference, sponsorship_levels, '#splash#sponsors'] do +- cache [conference, sponsors, sponsorship_levels, '#splash#sponsors'] do %section#sponsors .container - sponsorship_levels.each do |sponsorship_level| @@ -31,6 +31,6 @@ = link_to(sponsorship_mailto(conference)) do Contact us! -- sponsorship_levels.collect(&:sponsors).flatten.each do |sponsor| +- sponsors.each do |sponsor| - content_for :modals do = render 'modal_description', object: sponsor diff --git a/app/views/conferences/show.html.haml b/app/views/conferences/show.html.haml index ea99b419..246ccc35 100644 --- a/app/views/conferences/show.html.haml +++ b/app/views/conferences/show.html.haml @@ -43,7 +43,8 @@ -# sponsorship - if @conference.splashpage.include_sponsors = render 'sponsors', conference: @conference, - sponsorship_levels: @sponsorship_levels + sponsorship_levels: @sponsorship_levels, + sponsors: @sponsors -# footer - if @conference.splashpage.include_social_media From 7326bd132f38ec1ca28442001351acb5043af73e Mon Sep 17 00:00:00 2001 From: namangupta01 <01namangupta@gmail.com> Date: Tue, 8 Aug 2017 05:19:02 +0530 Subject: [PATCH 14/23] Ability of user to create registration is fixed Closes #1628 Speaker's ability to create registration and corresponding tests are improved --- app/models/ability.rb | 8 ++- spec/models/ability_spec.rb | 126 +++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 4 deletions(-) diff --git a/app/models/ability.rb b/app/models/ability.rb index b833b6f4..d6b3ef21 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -66,7 +66,13 @@ class Ability can [:new, :create], Registration do |registration| conference = registration.conference - conference.registration_open? && !conference.registration_limit_exceeded? || conference.program.speakers.confirmed.include?(user) + if conference.user_registered? user + false + elsif conference.program.speakers.confirmed.include?(user) && conference.registration_period + true + else + conference.registration_open? && !conference.registration_limit_exceeded? + end end can :index, Organization diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb index 7936ddbb..26522913 100644 --- a/spec/models/ability_spec.rb +++ b/spec/models/ability_spec.rb @@ -89,11 +89,131 @@ describe 'User' do let(:other_self_organized_track) { create(:track, :self_organized) } it{ should be_able_to(:manage, user) } - it{ should be_able_to(:manage, registration_public) } it{ should be_able_to(:manage, registration_not_public) } - it{ should_not be_able_to(:new, Registration.new(conference_id: conference_with_closed_registration.id))} - it{ should_not be_able_to(:create, Registration.new(conference_id: conference_with_closed_registration.id))} + + # Test for user can register or not + context 'when user is not a speaker with event confirmed' do + let(:conference) { create(:conference) } + + context 'when the registration is closed' do + before :each do + create(:registration_period, conference: conference, start_date: Date.current - 6.days, end_date: Date.current - 6.days) + end + + it{ should_not be_able_to(:new, Registration.new(conference: conference)) } + it{ should_not be_able_to(:create, Registration.new(conference: conference)) } + end + + context 'when the registration period is not set' do + it{ should_not be_able_to(:new, Registration.new(conference: conference)) } + it{ should_not be_able_to(:create, Registration.new(conference: conference)) } + end + + context 'when user has already registered' do + before :each do + create(:registration, conference: conference, user: user) + end + + it{ should_not be_able_to(:new, Registration.new(conference: conference)) } + it{ should_not be_able_to(:create, Registration.new(conference: conference)) } + end + + context 'when registrations are open' do + before :each do + create(:registration_period, conference: conference) + end + + it{ should be_able_to(:new, Registration.new(conference: conference)) } + it{ should be_able_to(:create, Registration.new(conference: conference)) } + + context 'when user has not registered with no registration_limit_exceeded' do + before :each do + conference.registration_limit = 1 + end + + it{ should be_able_to(:new, Registration.new(conference: conference)) } + it{ should be_able_to(:create, Registration.new(conference: conference)) } + end + + context 'when user has not registered with registration_limit_exceeded' do + before :each do + conference.registration_limit = 1 + create(:registration, conference: conference, user: user2) + end + + it{ should_not be_able_to(:new, Registration.new(conference: conference)) } + it{ should_not be_able_to(:create, Registration.new(conference: conference)) } + end + end + end + + context 'when user is a speaker with event confirmed' do + let(:conference_with_speaker_confirmed) { create(:conference) } + let(:event_with_speaker_confirmed) { create(:event, state: 'confirmed', program: conference_with_speaker_confirmed.program) } + + before :each do + event_with_speaker_confirmed.speakers << user + end + + context 'when registration period is not set' do + it{ should_not be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) } + it{ should_not be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) } + end + + context 'when speaker has already registered' do + before :each do + create(:registration, conference: conference_with_speaker_confirmed, user: user) + end + + it{ should_not be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) } + it{ should_not be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) } + end + + context 'when registration period is set' do + before :each do + create(:registration_period, conference: conference_with_speaker_confirmed) + end + + context 'when registrations are open' do + context 'when speaker has not registered' do + it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) } + it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) } + end + + context 'when registration_limit_exceeded' do + before :each do + conference_with_speaker_confirmed.registration_limit = 1 + create(:registration, conference: conference_with_speaker_confirmed, user: user2) + end + + it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) } + it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) } + end + end + + context 'when registrations are closed' do + before :each do + create(:registration_period, conference: conference_with_speaker_confirmed, start_date: Date.current - 6.days, end_date: Date.current - 6.days) + end + + context 'when speaker has not registered' do + it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) } + it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) } + end + + context 'with registration_limit_exceeded' do + before :each do + conference_with_speaker_confirmed.registration_limit = 1 + create(:registration, conference: conference_with_speaker_confirmed, user: user2) + end + + it{ should be_able_to(:new, Registration.new(conference: conference_with_speaker_confirmed)) } + it{ should be_able_to(:create, Registration.new(conference: conference_with_speaker_confirmed)) } + end + end + end + end it{ should be_able_to(:index, Ticket) } it{ should be_able_to(:manage, TicketPurchase.new(user_id: user.id)) } From d8f3933dc048cd352308d2381b1c8f6d8bd6a20a Mon Sep 17 00:00:00 2001 From: James Mason Date: Tue, 13 Feb 2018 09:30:16 -0800 Subject: [PATCH 15/23] Update Nokogiri re: CVE-2017-15412 --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0f64b0e8..38a4fce0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -297,7 +297,7 @@ GEM nenv (0.3.0) netrc (0.11.0) nio4r (2.1.0) - nokogiri (1.8.1) + nokogiri (1.8.2) mini_portile2 (~> 2.3.0) notiffany (0.1.1) nenv (~> 0.1) From 9c322d682f87a8934cb528e3fad825b37bb2eec2 Mon Sep 17 00:00:00 2001 From: ViditChitkara Date: Thu, 4 Jan 2018 18:45:39 +0530 Subject: [PATCH 16/23] fixed csv export bug --- app/models/registration.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/registration.rb b/app/models/registration.rb index 1198324e..45d2d55b 100644 --- a/app/models/registration.rb +++ b/app/models/registration.rb @@ -1,4 +1,5 @@ class Registration < ApplicationRecord + require 'csv' belongs_to :user belongs_to :conference From 5f7029d28e1a7750059f31bf0b7e28e7f02a7991 Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Sun, 18 Feb 2018 16:16:40 -0300 Subject: [PATCH 17/23] Make calculate_event_distribution use state to group events Signed-off-by: Carlos Coelho --- app/models/conference.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/conference.rb b/app/models/conference.rb index 03402652..81e9ec32 100644 --- a/app/models/conference.rb +++ b/app/models/conference.rb @@ -1029,7 +1029,7 @@ class Conference < ApplicationRecord # * +hash+ -> object_type => {color, value} def calculate_event_distribution(group_by_id, association_symbol, state = nil) grouped = if state - program.events.select(group_by_id).where('state = ?', 'confirmed').group(group_by_id) + program.events.select(group_by_id).where('state = ?', state).group(group_by_id) else program.events.select(group_by_id).group(group_by_id) end From 8457dafbf68fed04a57e5d938e52215c9306f3af Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Sun, 18 Feb 2018 16:17:29 -0300 Subject: [PATCH 18/23] Add withdrawn events to conference dashboard Signed-off-by: Carlos Coelho --- .rubocop_todo.yml | 4 +-- .../admin/conferences_controller.rb | 18 +++++++++-- app/views/admin/conferences/index.html.haml | 18 +++++++++-- app/views/admin/conferences/show.html.haml | 31 +++++++++++++++++-- 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index a4542c19..e4754e1e 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -300,7 +300,7 @@ Lint/UnusedBlockArgument: # Offense count: 136 Metrics/AbcSize: - Max: 86 + Max: 98 # Offense count: 258 # Configuration parameters: CountComments, ExcludedMethods. @@ -320,7 +320,7 @@ Metrics/LineLength: # Offense count: 133 # Configuration parameters: CountComments. Metrics/MethodLength: - Max: 56 + Max: 63 # Offense count: 4 # Configuration parameters: CountComments. diff --git a/app/controllers/admin/conferences_controller.rb b/app/controllers/admin/conferences_controller.rb index 921a23d1..6342f09f 100644 --- a/app/controllers/admin/conferences_controller.rb +++ b/app/controllers/admin/conferences_controller.rb @@ -20,6 +20,10 @@ module Admin @total_submissions = Event.count @new_submissions = Event.where('created_at > ?', current_user.last_sign_in_at).count + @total_withdrawn = Event.where(state: :withdrawn).count + @new_withdrawn = Event + .where('state = ? and created_at > ?', 'withdrawn', current_user.last_sign_in_at).count + @active_conferences = Conference.get_active_conferences_for_dashboard # pending or the last two @deactive_conferences = Conference .get_conferences_without_active_for_dashboard(@active_conferences) # conferences without active @@ -116,13 +120,19 @@ module Admin @total_reg = @conference.registrations.count @new_reg = @conference.registrations.where('created_at > ?', current_user.last_sign_in_at).count - @total_submissions = @program.events.count - @new_submissions = @program.events + @all_events = @program.events + + @total_submissions = @all_events.count + @new_submissions = @all_events .where('created_at > ?', current_user.last_sign_in_at).count @program_length = @conference.current_program_hours @new_program_length = @conference.new_program_hours(current_user.last_sign_in_at) + @total_withdrawn = @all_events.where(state: :withdrawn).count + @new_withdrawn = @all_events + .where('state = "withdrawn" and created_at > ?', current_user.last_sign_in_at).count + # Step by step list @conference_progress = @conference.get_status @@ -162,13 +172,17 @@ module Admin # Doughnut charts @event_type_distribution = @conference.event_type_distribution @event_type_distribution_confirmed = @conference.event_type_distribution(:confirmed) + @event_type_distribution_withdrawn = @conference.event_type_distribution(:withdrawn) @difficulty_levels_distribution = @conference.difficulty_levels_distribution @difficulty_levels_distribution_confirmed = @conference .difficulty_levels_distribution(:confirmed) + @difficulty_levels_distribution_withdrawn = @conference + .difficulty_levels_distribution(:withdrawn) @tracks_distribution = @conference.tracks_distribution @tracks_distribution_confirmed = @conference.tracks_distribution(:confirmed) + @tracks_distribution_withdrawn = @conference.tracks_distribution(:withdrawn) # Recent actions information @recent_events = @conference.program.events.limit(5).order(created_at: :desc) diff --git a/app/views/admin/conferences/index.html.haml b/app/views/admin/conferences/index.html.haml index 02208aeb..2fde1575 100644 --- a/app/views/admin/conferences/index.html.haml +++ b/app/views/admin/conferences/index.html.haml @@ -1,5 +1,5 @@ .row - .col-sm-4.col-xs-4 + .col-sm-3.col-xs-3 .dashbox.text-center %span.fa.fa-user.fa-lg %span.fa.fa-lg @@ -11,7 +11,7 @@ %span.label.label-success{ title: "+ #{@new_user} since you last logged in!" } + = @new_user - .col-sm-4.col-xs-4 + .col-sm-3.col-xs-3 .dashbox.text-center %span.fa.fa-check-square.fa-lg %span.fa.fa-lg @@ -23,7 +23,7 @@ %span.label.label-success{ title: "+#{@new_reg} since you last logged in!" } + = @new_reg - .col-sm-4.col-xs-4 + .col-sm-3.col-xs-3 .dashbox.text-center %span.fa.fa-file-text.fa-lg %span.fa.fa-lg @@ -35,6 +35,18 @@ %span.label.label-success{ title: "+#{@new_submissions} since you last logged in!" } + = @new_submissions + .col-sm-3.col-xs-3 + .dashbox.text-center + %span.fa.fa-archive.fa-lg + %span.fa.fa-lg + = @total_withdrawn + %p + %small + #{'Withdrawn'.pluralize(@total_withdrawn)} + - if @new_withdrawn + %span.label.label-success{ title: "+#{@new_withdrawn} since you last logged in!" } + + + = @new_withdrawn .row#registrations .col-md-8 diff --git a/app/views/admin/conferences/show.html.haml b/app/views/admin/conferences/show.html.haml index cddae4c2..ca59d8d9 100644 --- a/app/views/admin/conferences/show.html.haml +++ b/app/views/admin/conferences/show.html.haml @@ -3,7 +3,7 @@ Dashboard for #{@conference.title} %hr .row - .col-sm-4.col-xs-4 + .col-sm-3.col-xs-3 .dashbox.text-center %span.fa.fa-user.fa-lg %span.fa.fa-lg @@ -16,7 +16,7 @@ + = @new_reg - .col-sm-4.col-xs-4 + .col-sm-3.col-xs-3 .dashbox.text-center %span.fa.fa-check-square.fa-lg %span.fa.fa-lg @@ -29,7 +29,7 @@ + = @new_submissions - .col-sm-4.col-xs-4 + .col-sm-3.col-xs-3 .dashbox.text-center %span.fa.fa-file-text.fa-lg %span.fa.fa-lg @@ -42,6 +42,19 @@ + = @new_program_length + .col-sm-3.col-xs-3 + .dashbox.text-center + %span.fa.fa-archive.fa-lg + %span.fa.fa-lg + = @total_withdrawn + %p + %small + #{'Withdrawn'.pluralize(@total_withdrawn)} + - if @new_withdrawn + %span.label.label-success{ title: "+#{@new_withdrawn} since you last logged in!" } + + + = @new_withdrawn + .row .col-md-12 .row @@ -91,6 +104,10 @@ %a{ href: '#distribution_confirmed', 'data-toggle' => 'tab' } %span.fa.fa-comment Confirmed + %li + %a{ href: '#distribution_withdrawn', 'data-toggle' => 'tab' } + %span.fa.fa-archive + Withdrawn .tab-content .tab-pane.active#distribution_all .row @@ -108,6 +125,14 @@ = render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_confirmed} .col-md-4 = render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_confirmed} + .tab-pane#distribution_withdrawn + .row + .col-md-4 + = render partial: 'doughnut_chart', locals: {title: 'Event types', data: @event_type_distribution_withdrawn} + .col-md-4 + = render partial: 'doughnut_chart', locals: {title: 'Difficulty levels', data: @difficulty_levels_distribution_withdrawn} + .col-md-4 + = render partial: 'doughnut_chart', locals: {title: 'Tracks', data: @tracks_distribution_withdrawn} .row .col-md-8 From 637f6ce765efb4e2455874924c5ec32be90b93c6 Mon Sep 17 00:00:00 2001 From: Carlos Coelho Date: Sun, 18 Feb 2018 16:18:13 -0300 Subject: [PATCH 19/23] Add tests for conference withdrawn events --- .../admin/conferences_controller_spec.rb | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/spec/controllers/admin/conferences_controller_spec.rb b/spec/controllers/admin/conferences_controller_spec.rb index ff9d676b..984ef137 100644 --- a/spec/controllers/admin/conferences_controller_spec.rb +++ b/spec/controllers/admin/conferences_controller_spec.rb @@ -95,6 +95,75 @@ describe Admin::ConferencesController do get :show, id: conference.short_title expect(response).to render_template :show end + + it 'assigns conference withdrawn events distribution to event_type_distribution_withdrawn' do + conference + create(:event, program: conference.program) + workshop = create(:event_type, title: 'Workshop', color: '#000000', program: conference.program) + lecture = create(:event_type, title: 'Lecture', color: '#ffffff', program: conference.program) + get :show, id: conference.short_title + expect(assigns(:event_type_distribution_withdrawn)).to be_empty + create(:event, program: conference.program, state: 'withdrawn', event_type: lecture) + create(:event, program: conference.program, state: 'withdrawn', event_type: workshop) + get :show, id: conference.short_title + expect(assigns(:event_type_distribution_withdrawn)).not_to be_empty + result = {} + result['Workshop'] = { + 'value' => 1, + 'color' => '#000000' + } + result['Lecture'] = { + 'value' => 1, + 'color' => '#FFFFFF' + } + expect(assigns(:event_type_distribution_withdrawn)).to eq(result) + end + + it 'assigns conference withdrawn difficulty level distribution to difficulty_levels_distribution_withdrawn' do + conference + create(:event, program: conference.program) + get :show, id: conference.short_title + expect(assigns(:difficulty_levels_distribution_withdrawn)).to be_empty + easy = create(:difficulty_level, title: 'Easy', color: '#000000') + hard = create(:difficulty_level, title: 'Hard', color: '#ffffff') + create(:event, program: conference.program, state: 'withdrawn', difficulty_level: easy) + create(:event, program: conference.program, state: 'withdrawn', difficulty_level: hard) + get :show, id: conference.short_title + expect(assigns(:difficulty_levels_distribution_withdrawn)).not_to be_empty + result = {} + result['Easy'] = { + 'value' => 1, + 'color' => '#000000' + } + result['Hard'] = { + 'value' => 1, + 'color' => '#FFFFFF' + } + expect(assigns(:difficulty_levels_distribution_withdrawn)).to eq(result) + end + + it 'assigns conference withdrawn track distribution to tracks_distribution_withdrawn' do + conference + create(:event, program: conference.program) + get :show, id: conference.short_title + expect(assigns(:tracks_distribution_withdrawn)).to be_empty + track_one = create(:track, name: 'Track One', color: '#000000', program: conference.program) + track_two = create(:track, name: 'Track Two', color: '#FFFFFF', program: conference.program) + create(:event, program: conference.program, state: 'withdrawn', track: track_one) + create(:event, program: conference.program, state: 'withdrawn', track: track_two) + get :show, id: conference.short_title + expect(assigns(:tracks_distribution_withdrawn)).not_to be_empty + result = {} + result['Track One'] = { + 'value' => 1, + 'color' => '#000000' + } + result['Track Two'] = { + 'value' => 1, + 'color' => '#FFFFFF' + } + expect(assigns(:tracks_distribution_withdrawn)).to eq(result) + end end describe 'GET #index' do From 0c8095493a469071b64723de821ae68706ffdb2a Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Thu, 8 Feb 2018 22:29:58 -0800 Subject: [PATCH 20/23] Skylight instrumentation This allows individual installations to optionally collect performance data using [Skylight for Open Source](https://www.skylight.io/oss). --- Gemfile | 3 ++ Gemfile.lock | 3 ++ INSTALL.md | 7 ++++ app/views/layouts/application.html.haml | 9 +++-- dotenv.example | 4 ++ .../application_controller_spec.rb | 40 ++++++++++++++++++- 6 files changed, 62 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index e624a1f7..9be883a3 100644 --- a/Gemfile +++ b/Gemfile @@ -209,6 +209,9 @@ gem 'sprockets-rails' # for multiple speakers select on proposal/event forms gem 'selectize-rails' +# For collecting performance data +gem 'skylight' + # Nokogiri < 1.8.1 is subject to: # CVE-2017-0663, CVE-2017-7375, CVE-2017-7376, CVE-2017-9047, CVE-2017-9048, # CVE-2017-9049, CVE-2017-9050 diff --git a/Gemfile.lock b/Gemfile.lock index 38a4fce0..9e07eb20 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -505,6 +505,8 @@ GEM simplecov-html (~> 0.10.0) simplecov-html (0.10.0) sixarm_ruby_unaccent (1.1.1) + skylight (1.5.1) + activesupport (>= 3.0.0) slop (3.6.0) sort_alphabetical (1.0.2) unicode_utils (>= 1.2.2) @@ -668,6 +670,7 @@ DEPENDENCIES sass-rails (>= 4.0.2) selectize-rails shoulda-matchers + skylight spring-commands-rspec sprockets-rails sqlite3 diff --git a/INSTALL.md b/INSTALL.md index ea47fd93..06249929 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -106,6 +106,8 @@ There are a couple of environment variables you can set to configure OSEM. Check | STRIPE_PUBLISHABLE_KEY | *string* | Publishable Key for Stripe Gateway | STRIPE_SECRET_KEY | *string* | Secret Key for Stripe Gateway | OSEM_REDIS_URL | *string* | Redis server URL e.g. redis://localhost:6379/1 +| SKYLIGHT_AUTHENTICATION | *string* | (Optional) Authentication token for Skylight +| SKYLIGHT_PUBLIC_DASHBOARD_URL | *string* | (Optional) URL to your public Skylight dashboard ### Online Ticket Payments We use [Stripe](https://stripe.com) for accepting your ticket payments securely over the web. @@ -130,3 +132,8 @@ Open a separate terminal and go into the directory where the rails app is presen ``` bundle exec rake jobs:work ``` + +## Performance +If you are experiencing performance issues (or just curious), you may be able to [apply a free Skylight account](https://www.skylight.io/oss). +Once you have your account setup, simply set `SKYLIGHT_AUTHENTICATION` and `SKYLIGHT_PUBLIC_DASHBOARD_URL` in your `.env` file. +If you are reporting a performance issue or submiting a performance patch, it would be helpful (but not required) to link to the relevant Skylight data. diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index aa155bcb..128f491a 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -37,11 +37,14 @@ %p.muted.text-center %small This tool is - =link_to "free software,", "http://www.gnu.org/philosophy/free-sw.html" + #{link_to "free software", "http://www.gnu.org/philosophy/free-sw.html"}, released under the - =link_to "MIT license.", "http://opensource.org/licenses/MIT" + #{link_to "MIT license", "http://opensource.org/licenses/MIT"}. You can run, copy, distribute, study, change and improve it. The source code and the developers are on - =link_to "github.", "https://github.com/openSUSE/osem" + #{link_to "GitHub", "https://github.com/openSUSE/osem"}. + - if ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"].present? + Performance data is available on + #{link_to "Skylight", ENV["SKYLIGHT_PUBLIC_DASHBOARD_URL"]}. = yield :script_body = piwik_tracking_tag diff --git a/dotenv.example b/dotenv.example index e0e3f519..6d8dd025 100644 --- a/dotenv.example +++ b/dotenv.example @@ -46,6 +46,10 @@ OSEM_SUSE_SECRET='' STRIPE_PUBLISHABLE_KEY='' STRIPE_SECRET_KEY='' +# (OPTIONAL) Skylight keys. See https://www.skylight.io/oss. +# SKYLIGHT_AUTHENTICATION='' +# SKYLIGHT_PUBLIC_DASHBOARD_URL='https://oss.skylight.io/app/applications/xxxxxxxxxxxx' + # Disable linting of factories in the test suite. # Speeds up turn around times of tests OSEM_FACTORY_LINT="false" diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 214e522a..4d1c2eab 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -30,7 +30,45 @@ describe ApplicationController, type: :controller do expect(controller.after_sign_in_path_for(user)).to eq conferences_path end end - + end + + end + +end + +describe ApplicationController, type: :request do + let(:conference) { create(:conference) } + + describe 'Skylight link' do + + around do |example| + original_value = ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] + example.run + ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] = original_value + end + + context 'when SKYLIGHT_PUBLIC_DASHBOARD_URL is set' do + before do + ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] = 'https://oss.skylight.io/app/applications/my-osem' + end + + it 'should include a link to view performance data' do + get '/' + expect(response.body).to match(/Performance data/i) + expect(response.body).to include('https://oss.skylight.io/app/applications/my-osem') + end + end + + context 'when SKYLIGHT_PUBLIC_DASHBOARD_URL is not set' do + before do + ENV['SKYLIGHT_PUBLIC_DASHBOARD_URL'] = nil + end + + it 'should not include a link to view performance data' do + get '/' + expect(response.body).to_not match(/performance data/i) + expect(response.body).to_not match(/skylight/i) + end end end From 281022a80ce98ba57c890b858dabe355066c2268 Mon Sep 17 00:00:00 2001 From: Jason Taylor Date: Tue, 16 Jan 2018 15:22:15 +1300 Subject: [PATCH 21/23] add .pdf file extension for ticket download --- app/controllers/physical_tickets_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/physical_tickets_controller.rb b/app/controllers/physical_tickets_controller.rb index 2f6f18ec..c3cc40cb 100644 --- a/app/controllers/physical_tickets_controller.rb +++ b/app/controllers/physical_tickets_controller.rb @@ -10,7 +10,7 @@ class PhysicalTicketsController < ApplicationController end def show - @file_name = "ticket_for_#{@conference.short_title}" + @file_name = "ticket_for_#{@conference.short_title}.pdf" @user = @physical_ticket.user @ticket_layout = @conference.ticket_layout.to_sym @qrcode_image = RQRCode::QRCode.new(@physical_ticket.token).as_png(size: 180, border_modules: 0) From b1960c08efe3e2018938d3e448f18f115a0fcd59 Mon Sep 17 00:00:00 2001 From: Marie-Elise Date: Mon, 15 Jan 2018 22:14:22 -0600 Subject: [PATCH 22/23] Added name uniqueness validation for organization model. --- app/models/organization.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/models/organization.rb b/app/models/organization.rb index 21d0989b..1e3974de 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -7,7 +7,11 @@ class Organization < ApplicationRecord after_create :create_roles - validates :name, presence: true + validates :name, + uniqueness: { + case_sensitive: false + }, + presence: true mount_uploader :picture, PictureUploader, mount_on: :picture From 44fd794416c72b7c5e034aa87672f2d6e14579ab Mon Sep 17 00:00:00 2001 From: James Mason Date: Wed, 28 Feb 2018 09:34:43 -0800 Subject: [PATCH 23/23] Make test organization names more unique The addition of a uniqueness validation on Organization#name is causing a lot of random failures; the Organization factory uses a Faker value, but appears to be producing repetitive results, so I've added a FactoryGirl sequence to ensure uniqueness. --- spec/factories/organizations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/factories/organizations.rb b/spec/factories/organizations.rb index 0ee76554..f6331873 100644 --- a/spec/factories/organizations.rb +++ b/spec/factories/organizations.rb @@ -1,6 +1,6 @@ FactoryGirl.define do factory :organization do - name { Faker::Company.name } + sequence(:name) { |n| "#{Faker::Company.name} #{n}" } description { Faker::Lorem.paragraph } # after(:create) do |organization|