Skip to content

Instantly share code, notes, and snippets.

@sergeykish
Created September 11, 2010 15:30
Show Gist options
  • Save sergeykish/575274 to your computer and use it in GitHub Desktop.
Save sergeykish/575274 to your computer and use it in GitHub Desktop.
shoulda and jasmine example
class Event < ActiveRecord::Base
include ValidUrlHelper
include Importable
include ImageAccessors
belongs_to :text_entry
belongs_to :cluster
belongs_to :user
has_many :external_photos, :as => :photo_holder, :dependent => :destroy
has_many :photos, :as => :photo_holder, :dependent => :destroy
has_many :favorites, :as => :favorable
has_many :subscribers, :through => :favorites, :class_name => 'User', :source => :user
has_many :taggings, :as => :attachable, :dependent => :destroy
has_many :tags, :through => :taggings, :uniq => true
accepts_nested_attributes_for :photos, :reject_if => proc { |obj| obj.symbolize_keys[:data].blank? }
delegate :user, :to => :text_entry
validate :validate_dates
validates_presence_of :started_at_date
validates_presence_of :title
validates_presence_of :text_entry
validates_format_of :url, :with => URL_REG_EXP, :message => "Bitte gib eine gültige URL an!", :if => proc {|entry| !entry.url.blank?}
def validate_dates
if started_at && ended_at
errors.add(:formatted_ended_at_date, 'Bitte gib einen Endtermin ein, der nach dem Starttermin endet.') if ended_at < started_at
errors.add(:formatted_ended_at_date, 'Der Endtermin ist älter als 7 Tage.') if ended_at < 7.days.ago
end
if started_at && ended_at.nil?
errors.add(:formatted_started_at_date, 'Der Starttermin ist älter als 7 Tage (und kein Endtermin vorhanden)') if started_at < 7.days.ago
end
end
STARTED_AT_SQL = "(started_at_date + coalesce(started_at_time, time '00:00'))"
ENDED_AT_SQL = "(ended_at_date + coalesce(ended_at_time, time '00:00'))"
named_scope :active_scope, :conditions => ["#{STARTED_AT_SQL} >= :from_date OR :until_date <= #{ENDED_AT_SQL}",
{:from_date => DateTime.now.beginning_of_day, :until_date => DateTime.now.end_of_day}]
named_scope :order_by_start_date, lambda {
{ :order => ["#{STARTED_AT_SQL} ASC, id"] }
}
named_scope :owned_by, lambda {|user|
{
:joins => :text_entry,
:conditions => ['text_entries.user_id=?', user.id],
:order => "started_at_date, started_at_time ASC"
}
}
named_scope :visible_for, lambda { |user|
if user && !user.guest?
{
:conditions => ['NOT (visible_te.hidden OR events.hidden) OR visible_te.user_id = ?', user.id],
:joins => "JOIN text_entries visible_te ON (visible_te.id = events.text_entry_id)"
}
else
{
:conditions => ['NOT (visible_te.hidden OR events.hidden)'],
:joins => "JOIN text_entries visible_te ON (visible_te.id = events.text_entry_id)"
}
end
}
def to_param
"#{self.id}-#{self.title.parameterize}"
end
def days
@days ||= if ended_at_date.nil?
1
else
(ended_at_date.to_date - started_at_date.to_date).to_i + 1
end
end
# ...
require 'test_helper'
class EventTest < ActiveSupport::TestCase
should_belong_to :text_entry
should_validate_presence_of :title, :started_at_date, :text_entry
context "date validations" do
should "not accept event with startdate after enddate" do
assert_raise ActiveRecord::RecordInvalid do
Factory(:event, :started_at_date => 10.days.from_now, :ended_at_date => 5.days.from_now)
end
end
should "not accept events with start_date older than 7 days (if no end_date set)" do
assert_raise ActiveRecord::RecordInvalid do
Factory(:event, :started_at_date => 8.days.ago, :ended_at_date => nil)
end
end
should "not accept events with end_date older than 7 days" do
assert_raise ActiveRecord::RecordInvalid do
Factory(:event, :started_at_date => 10.days.ago, :ended_at_date => 8.days.ago)
end
end
end
context "privacy" do
setup do
@user = Factory(:active_user)
@other_user = Factory(:active_user)
@private_location = Factory(:private_text_entry, :user => @user)
@private_location_private_event = Factory(:private_event, :text_entry => @private_location)
@private_location_visible_event = Factory(:event, :text_entry => @private_location)
@visible_location = Factory(:text_entry, :user => @user)
@visible_location_private_event = Factory(:private_event, :text_entry => @visible_location)
@visible_location_visible_event = Factory(:event, :text_entry => @visible_location)
end
should "find hidden events for owner" do
assert_same_elements [
@visible_location_private_event,
@visible_location_visible_event,
@private_location_private_event,
@private_location_visible_event],
Event.visible_for(@user)
end
should "not leak private information for other users" do
assert_same_elements [@visible_location_visible_event], Event.visible_for(@other_user)
end
should "not leak private information to unknown user" do
assert_same_elements [@visible_location_visible_event], Event.visible_for(nil)
end
end
context "days calculation" do
should "be 1 day unless ended_at_date specified" do
e = Factory(:event, :ended_at_date => nil)
assert_equal 1, e.days
end
should "calculate including the start and end days" do
e = Factory(:event, :started_at_date => 1.day.ago, :ended_at_date => 1.day.from_now)
assert_equal 3, e.days
end
end
context "active_scope" do
should "return only future events" do
future_event = Factory(:event, :started_at_date => 1.days.from_now)
past_event = Factory(:event, :started_at_date => 1.days.ago, :ended_at_date => 1.days.ago)
events = Event.active_scope
assert events.include?(future_event)
assert !events.include?(past_event)
end
end
# ...
(function($) {
$.PaginationCalculator = function(count) {
this.count = count;
}
$.extend($.PaginationCalculator.prototype, {
range: function(current) {
var result = [];
for(var i = current - 2; i <= current + 2; i++) {
if(i >= 1 && i <= this.count) {
result.push(i);
}
}
return result;
}
});
$.PaginationRenderer = function(count, current) {
this.count = count;
this.current = current;
this.pc = new $.PaginationCalculator(count);
}
$.extend($.PaginationRenderer.prototype, {
createLink: function(id, appendopts) {
id = id < 1 ? 1 : (id <= this.count ? id : this.count);
appendopts = $.extend({text: id}, appendopts || {});
return $(id == this.current ? '<span></span>' : "<a></a>", appendopts).data('page', id);
},
rangeLinks:function() {
var range = this.pc.range(this.current);
var result = [];
for (var i = 0; i < range.length; i++) {
result.push(this.createLink(range[i], {"class":"page"}));
};
if (result.length > 0) {
result[0].addClass('first');
};
return result;
},
getLinks: function(current, handler) {
var fragment = $("<span class='pagination'></span>")
this.createLink(this.currentPage - 1, {
text:'zurück',
"class":"previous"
}).appendTo(fragment);
$.fn.append.apply(fragment, this.rangeLinks());
this.createLink(this.currentPage + 1, {
text:'weiter',
"class":"next"
}).appendTo(fragment);
fragment.find('a')
.attr('href', function() {return Loxicon.hashWithParam('page', $(this).data('page'))})
.click(handler);
return fragment;
}
});
// ...
describe("Pagination", function() {
describe("range calculation", function() {
it("should change size depending on current", function() {
var pc = new $.PaginationCalculator(6);
expect(pc.range(1)).toEqual([1, 2, 3]);
expect(pc.range(2)).toEqual([1, 2, 3, 4]);
expect(pc.range(6)).toEqual([4, 5, 6]);
expect(pc.range(5)).toEqual([3, 4, 5, 6]);
expect(pc.range(3)).toEqual([1, 2, 3, 4, 5]);
});
it("should limit to total", function() {
var pc;
pc = new $.PaginationCalculator(3);
expect(pc.range(2)).toEqual([1, 2, 3]);
pc = new $.PaginationCalculator(2);
expect(pc.range(2)).toEqual([1, 2]);
});
});
describe("links render", function() {
beforeEach(function() {
this.pr = new $.PaginationRenderer(6, 3);
});
it("should create current as span", function() {
expect(this.pr.createLink(this.pr.current)).toBe("span");
});
it("should create other as anchor", function() {
expect(this.pr.createLink(this.pr.current + 1)).toBe("a");
});
it("should append optional params", function() {
var link = this.pr.createLink(1, {text:"zurück", "class":"prev"});
expect(link).toBe(".prev");
expect(link).toHaveText("zurück")
});
});
// ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment