diff --git a/.travis.yml b/.travis.yml
index b11346b..4a53bc3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,12 @@ gemfile:
- gemfiles/spree_3_2.gemfile
- gemfiles/spree_master.gemfile
+before_script:
+ - mkdir ../temp; cd ../temp
+ - bundle exec rails _5.1.1_ plugin new spree_slider --mountable --dummy-path=spec/dummy --skip-test-unit
+ - mv spree_slider/spec/dummy ../spec/
+ - cd ../build; rm -rf ../temp
+
script:
- bundle exec rspec spec
diff --git a/app/controllers/spree/admin/slides_controller.rb b/app/controllers/spree/admin/slides_controller.rb
index 4a86b4c..0c13da4 100644
--- a/app/controllers/spree/admin/slides_controller.rb
+++ b/app/controllers/spree/admin/slides_controller.rb
@@ -18,7 +18,16 @@ def location_after_save
end
def slide_params
- params.require(:slide).permit(:name, :body, :link_url, :published, :image, :position, :product_id)
+ params.require(:slide)
+ .permit(:name,
+ :body,
+ :link_url,
+ :published,
+ :image,
+ :position,
+ :product_id,
+ :starts_at,
+ :ends_at)
end
end
end
diff --git a/app/models/spree/slide.rb b/app/models/spree/slide.rb
index c8d8774..c5df8bf 100644
--- a/app/models/spree/slide.rb
+++ b/app/models/spree/slide.rb
@@ -1,5 +1,4 @@
class Spree::Slide < ActiveRecord::Base
-
has_and_belongs_to_many :slide_locations,
class_name: 'Spree::SlideLocation',
join_table: 'spree_slide_slide_locations'
@@ -8,13 +7,21 @@ class Spree::Slide < ActiveRecord::Base
url: '/spree/slides/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/slides/:id/:style/:basename.:extension',
convert_options: { all: '-strip -auto-orient -colorspace sRGB' }
- validates_attachment :image, content_type: { content_type: ["image/jpg", "image/jpeg", "image/png", "image/gif"] }
+ validates_attachment :image, content_type: { content_type: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif'] }
scope :published, -> { where(published: true).order('position ASC') }
- scope :location, -> (location) { joins(:slide_locations).where('spree_slide_locations.name = ?', location) }
+ scope :location, ->(location) { joins(:slide_locations).where('spree_slide_locations.name = ?', location) }
belongs_to :product, touch: true
+ def self.active_for_current_time
+ where '(starts_at is NULL AND ends_at is NULL)
+ OR (starts_at <= ? AND ends_at is NULL)
+ OR (starts_at is NULL AND ends_at >= ?)
+ OR (starts_at <= ? AND ends_at >= ?)',
+ *([Time.current] * 4)
+ end
+
def initialize(attrs = nil)
attrs ||= { published: true }
super
@@ -31,4 +38,8 @@ def slide_link
def slide_image
!image.file? && product.present? && product.images.any? ? product.images.first.attachment : image
end
+
+ def active_now?
+ Time.current.between?(starts_at || 1.second.ago, ends_at || 1.second.from_now)
+ end
end
diff --git a/app/models/spree/slide_location.rb b/app/models/spree/slide_location.rb
index 6993052..04b5b3f 100644
--- a/app/models/spree/slide_location.rb
+++ b/app/models/spree/slide_location.rb
@@ -1,9 +1,10 @@
class Spree::SlideLocation < ActiveRecord::Base
-
has_and_belongs_to_many :slides,
+ ->(model) { where('spree_slides.id != ?', model.fallback_slide_id || 0) },
class_name: 'Spree::Slide',
join_table: 'spree_slide_slide_locations'
- validates :name, presence: true
+ belongs_to :fallback_slide, class_name: 'Spree::Slide', foreign_key: 'fallback_slide_id'
+ validates :name, presence: true
end
diff --git a/app/views/spree/admin/slide_locations/_form.html.erb b/app/views/spree/admin/slide_locations/_form.html.erb
index 593aa1a..b6daef6 100644
--- a/app/views/spree/admin/slide_locations/_form.html.erb
+++ b/app/views/spree/admin/slide_locations/_form.html.erb
@@ -5,6 +5,12 @@
<%= f.label :name, t(:name) %>
<%= f.text_field :name, class: "form-control fullwidth" %>
<% end %>
+
+ <%= f.field_container :fallback_slide_id do %>
+ <%= f.label :fallback_slide_id, 'Fallback slide' %>
+
This slide will be shown only when no other slide can be shown.
+ <%= f.collection_select(:fallback_slide_id, Spree::Slide.all.order(:name), :id, :name, { include_blank: Spree.t('match_choices.none') }, { class: 'select2', disabled: (cannot? :edit, Spree::SlideLocation) }) %>
+ <% end %>
diff --git a/app/views/spree/admin/slide_locations/index.html.erb b/app/views/spree/admin/slide_locations/index.html.erb
index f45ee4c..e99b967 100644
--- a/app/views/spree/admin/slide_locations/index.html.erb
+++ b/app/views/spree/admin/slide_locations/index.html.erb
@@ -10,6 +10,7 @@
<%= Spree.t(:name) %> |
+ Fallback slide |
|
@@ -17,6 +18,14 @@
<% @slide_locations.each do |location|%>
<%= location.name %> |
+
+ <% if location.fallback_slide %>
+ <%= image_tag location.fallback_slide.try(:slide_image), style: 'width: 120px; height: auto;' %>
+ <%= link_to location.fallback_slide.name, admin_slide_path(location.fallback_slide) %>
+ <% else %>
+ None
+ <% end %>
+ |
<%= link_to_edit location, no_text: true, class: 'edit' %>
diff --git a/app/views/spree/admin/slides/_form.html.erb b/app/views/spree/admin/slides/_form.html.erb
index 529321e..5ca0bd3 100644
--- a/app/views/spree/admin/slides/_form.html.erb
+++ b/app/views/spree/admin/slides/_form.html.erb
@@ -36,6 +36,22 @@
<% end %>
+
+ <%= f.field_container :starts_at do %>
+ <%= f.label :starts_at, 'Starts at' %>
+ The slide will not be shown before this date, even if published
+ <%= f.date_field :starts_at, class: 'fullwidth form-control' %>
+ <% end %>
+
+
+
+ <%= f.field_container :ends_at do %>
+ <%= f.label :ends_at, 'Ends at' %>
+ The slide will not be shown after this date, even if published
+ <%= f.date_field :ends_at, class: 'fullwidth form-control' %>
+ <% end %>
+
+
<%= render 'spree/admin/slides/edit_slider_locations', f: f %>
diff --git a/db/migrate/20170906023647_add_starts_at_and_ends_at_columns_to_spree_slides.rb b/db/migrate/20170906023647_add_starts_at_and_ends_at_columns_to_spree_slides.rb
new file mode 100644
index 0000000..75eb33c
--- /dev/null
+++ b/db/migrate/20170906023647_add_starts_at_and_ends_at_columns_to_spree_slides.rb
@@ -0,0 +1,6 @@
+class AddStartsAtAndEndsAtColumnsToSpreeSlides < ActiveRecord::Migration
+ def change
+ add_column :spree_slides, :starts_at, :datetime
+ add_column :spree_slides, :ends_at, :datetime
+ end
+end
diff --git a/db/migrate/20170907185000_add_fallback_slide_column.rb b/db/migrate/20170907185000_add_fallback_slide_column.rb
new file mode 100644
index 0000000..312a6ac
--- /dev/null
+++ b/db/migrate/20170907185000_add_fallback_slide_column.rb
@@ -0,0 +1,5 @@
+class AddFallbackSlideColumn < ActiveRecord::Migration
+ def change
+ add_column 'spree_slide_locations', :fallback_slide_id, :integer, default: nil
+ end
+end
diff --git a/spec/models/spree/slide_location_spec.rb b/spec/models/spree/slide_location_spec.rb
new file mode 100644
index 0000000..608434a
--- /dev/null
+++ b/spec/models/spree/slide_location_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+RSpec.describe Spree::SlideLocation do
+ let(:slide1) { Spree::Slide.create }
+ let(:slide2) { Spree::Slide.create }
+
+ describe '#slides' do
+ before do
+ Spree::SlideLocation.create name: 'Test location',
+ slides: [slide1, slide2],
+ fallback_slide: slide1
+ end
+
+ it 'doesnt include its fallback slide' do
+ location = Spree::SlideLocation.find_by! name: 'Test location'
+ expect(location.slides.map(&:id)).to contain_exactly slide2.id
+ end
+ end
+end
diff --git a/spec/models/spree/slide_spec.rb b/spec/models/spree/slide_spec.rb
new file mode 100644
index 0000000..40ad1e5
--- /dev/null
+++ b/spec/models/spree/slide_spec.rb
@@ -0,0 +1,68 @@
+require 'spec_helper'
+
+RSpec.describe Spree::Slide do
+ describe '#active_now?' do
+ context 'when both starts_at and ends_at are nil' do
+ subject { Spree::Slide.new starts_at: nil, ends_at: nil }
+
+ it { is_expected.to be_active_now }
+ end
+
+ context 'when starts_at is in the past and ends_at is nil' do
+ subject { Spree::Slide.new starts_at: 2.days.ago, ends_at: nil }
+
+ it { is_expected.to be_active_now }
+ end
+
+ context 'when starts_at is in the future and ends_at is nil' do
+ subject { Spree::Slide.new starts_at: 2.days.from_now, ends_at: nil }
+
+ it { is_expected.not_to be_active_now }
+ end
+
+ context 'when starts_at is nil and ends_at is in the future' do
+ subject { Spree::Slide.new starts_at: nil, ends_at: 2.days.from_now }
+
+ it { is_expected.to be_active_now }
+ end
+
+ context 'when starts_at is nil and ends_at is in the past' do
+ subject { Spree::Slide.new starts_at: nil, ends_at: 2.days.ago }
+
+ it { is_expected.not_to be_active_now }
+ end
+
+ context 'when both starts_at and end_at is in the past' do
+ subject { Spree::Slide.new starts_at: 2.days.ago, ends_at: 1.day.ago }
+
+ it { is_expected.not_to be_active_now }
+ end
+
+ context 'when starts_at is in the past and end_at is in the future' do
+ subject { Spree::Slide.new starts_at: 2.days.ago, ends_at: 2.days.from_now }
+
+ it { is_expected.to be_active_now }
+ end
+ end
+
+ describe '.active_for_current_time' do
+ it 'returns all the slides from the database that are active for current time' do
+ good_slides = [
+ Spree::Slide.create(starts_at: nil, ends_at: nil),
+ Spree::Slide.create(starts_at: 2.days.ago, ends_at: nil),
+ Spree::Slide.create(starts_at: nil, ends_at: 2.days.from_now),
+ Spree::Slide.create(starts_at: 2.days.ago, ends_at: 2.days.from_now)
+ ].map(&:id)
+
+ bad_slides = [
+ Spree::Slide.create(starts_at: 2.days.from_now, ends_at: nil),
+ Spree::Slide.create(starts_at: nil, ends_at: 2.days.ago),
+ Spree::Slide.create(starts_at: 2.days.ago, ends_at: 1.day.ago)
+ ].map(&:id)
+
+ slides = Spree::Slide.active_for_current_time.map(&:id)
+ expect(slides).to include *good_slides
+ expect(slides).not_to include *bad_slides
+ end
+ end
+end
|