qcontent 0.1.0

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.
@@ -0,0 +1,9 @@
1
+ == 0.1.0 2009-03-20
2
+
3
+ * 1 major enhancement
4
+ * first full release
5
+
6
+ == 0.0.1 2009-01-09
7
+
8
+ * 1 major enhancement:
9
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Aaron Quint, Quirkey NYC, LLC
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ 'Software'), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ History.txt
2
+ LICENSE
3
+ Manifest.txt
4
+ PostInstall.txt
5
+ README.rdoc
6
+ Rakefile
7
+ init.rb
8
+ lib/qcontent.rb
9
+ lib/qcontent/assets.rb
10
+ lib/qcontent/dimension.rb
11
+ lib/qcontent/extensions.rb
12
+ lib/qcontent/pricing.rb
13
+ lib/qcontent/published.rb
14
+ qcontent.gemspec
15
+ rails/init.rb
16
+ test/test_dimension.rb
17
+ test/test_helper.rb
18
+ test/test_qcontent.rb
@@ -0,0 +1,3 @@
1
+ For more information on qcontent, see http://code.quirkey.com/qcontent
2
+
3
+
@@ -0,0 +1,31 @@
1
+ = qcontent
2
+
3
+ http://github.com/quirkey/qcontent
4
+
5
+ == DESCRIPTION:
6
+
7
+ qcontent is a set of modules to be included mainly in ActiveRecord::Base models to extend the functionality. The modules are mainly aimed at Content like classes or models to be used in a Content Management System e.g. Articles, Videos, etc.
8
+
9
+ == USAGE:
10
+
11
+ Please see the project homepage for usage and more info:
12
+
13
+ http://code.quirkey.com/qcontent
14
+
15
+ == INSTALL:
16
+
17
+ To install as a gem:
18
+
19
+ sudo gem install qcontent
20
+
21
+ or from github:
22
+
23
+ sudo gem install quirkey-qcontent -s http://gems.github.com
24
+
25
+ To install as a rails plugin:
26
+
27
+ ./script/plugin install git://github.com/quirkey/qcontent.git
28
+
29
+ == LICENSE:
30
+
31
+ Free for use under the terms of the MIT License - see LICENSE for details
@@ -0,0 +1,30 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/qcontent'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('qcontent', Qcontent::VERSION) do |p|
7
+ p.developer('Aaron Quint', 'aaron@quirkey.com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = 'quirkey' # TODO this is default value
11
+ p.summary = p.description = 'Modules and Mixins for extending ActiveRecord models for content management systems'
12
+ p.extra_deps = [
13
+ ['activesupport','>= 2.2.0'],
14
+ ['money','>= 2.0.0']
15
+ ]
16
+ p.extra_dev_deps = [
17
+ ['newgem', ">= #{::Newgem::VERSION}"]
18
+ ]
19
+
20
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
21
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
22
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
23
+ p.rsync_args = '-av --delete --ignore-errors'
24
+ end
25
+
26
+ require 'newgem/tasks' # load /tasks/*.rake
27
+ Dir['tasks/**/*.rake'].each { |t| load t }
28
+
29
+ # TODO - want other tests/tasks run by default? Add them to the list
30
+ # task :default => [:spec, :features]
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "rails", "init")
@@ -0,0 +1,22 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ module Qcontent
5
+ VERSION = '0.1.0'
6
+
7
+ def content_type
8
+ self.class.to_s.tableize
9
+ end
10
+
11
+ end
12
+
13
+ require 'rubygems'
14
+ require 'money'
15
+
16
+ %w{
17
+ extensions
18
+ pricing
19
+ assets
20
+ dimension
21
+ published
22
+ }.each {|lib| require "qcontent/#{lib}" }
@@ -0,0 +1,72 @@
1
+ module Qcontent
2
+ module Assets
3
+
4
+ def self.included(klass)
5
+ klass.extend Qcontent::Assets::Macros
6
+ end
7
+
8
+ module Macros
9
+
10
+ def has_assets(group_name, options = {})
11
+
12
+ has_many :content_assets, :as => :content, :dependent => :delete_all
13
+ has_many "content_#{group_name}", :class_name => 'ContentAsset',
14
+ :order => 'content_assets.position ASC',
15
+ :as => :content,
16
+ :conditions => "content_assets.asset_group = '#{group_name}'"
17
+ has_many group_name, :through => "content_#{group_name}", :source => :asset
18
+ include InstanceMethods
19
+
20
+ alias_method "#{group_name}_association=", "#{group_name}="
21
+
22
+ after_save :save_assets
23
+
24
+ self.class_eval <<-EOT
25
+ def #{group_name}=(hash_of_assets)
26
+ return unless hash_of_assets
27
+ if hash_of_assets.is_a?(Array) && hash_of_assets.first.is_a?(Asset)
28
+ self.#{group_name}_association = hash_of_assets
29
+ else
30
+ collect_assets_to_save(:#{group_name}, hash_of_assets)
31
+ end
32
+ end
33
+
34
+ def #{group_name.to_s.singularize}
35
+ self.#{group_name}.first
36
+ end
37
+ EOT
38
+ end
39
+
40
+ end
41
+
42
+ module InstanceMethods
43
+
44
+ def collect_assets_to_save(group, hash_of_assets)
45
+ return unless hash_of_assets
46
+ @assets_to_save ||= {}
47
+ @assets_to_save[group.to_s] = hash_of_assets
48
+ end
49
+
50
+ def save_assets
51
+ logger.debug '== Saving Assets'
52
+ return unless @assets_to_save
53
+ @assets_to_save.each do |group_name, asset_group|
54
+ logger.debug '--- Deleting the whole group'
55
+ self.send("content_#{group_name}").delete_all
56
+ logger.debug "--- Saving Asset group #{group_name} on #{self}"
57
+ asset_group.each do |position, asset_attributes|
58
+ logger.debug "---- #{position}: #{asset_attributes.inspect}"
59
+ if asset_attributes.is_a?(Hash)
60
+ asset = Asset.create({:dir => group_name.to_s}.merge(asset_attributes))
61
+ self.content_assets.create(:asset_id => asset.id, :position => position, :asset_group => group_name.to_s) if asset
62
+ elsif asset_attributes.to_i > 0
63
+ self.content_assets.create(:asset_id => asset_attributes.to_i, :position => position, :asset_group => group_name.to_s)
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,45 @@
1
+ module Qcontent
2
+ class Dimension
3
+ class InvalidDimension < ::RuntimeError; end;
4
+ include Comparable
5
+
6
+ attr_accessor :width, :height
7
+
8
+ def initialize(*args)
9
+ first = args.shift
10
+ case first
11
+ when Array
12
+ self.width, self.height = first
13
+ when Hash
14
+ self.width = first['width'] || first[:width]
15
+ self.height = first['height'] || first[:height]
16
+ when Dimension
17
+ return first
18
+ else
19
+ self.width, self.height = (first.is_a?(String) ? first.split('x') : first)
20
+ self.height ||= args.shift
21
+ end
22
+ end
23
+
24
+ def ==(other)
25
+ self.width == other.width && self.height == other.height
26
+ end
27
+
28
+ def width=(w)
29
+ @width = w.nil? ? nil : w.to_i
30
+ end
31
+
32
+ def height=(h)
33
+ @height = h.nil? ? nil : h.to_i
34
+ end
35
+
36
+ def to_s(join = 'x')
37
+ "#{width}#{join}#{height}"
38
+ end
39
+
40
+ def to_a
41
+ [width, height]
42
+ end
43
+
44
+ end
45
+ end
@@ -0,0 +1,5 @@
1
+ class Money
2
+ def to_i
3
+ cents
4
+ end
5
+ end
@@ -0,0 +1,71 @@
1
+ module Qcontent
2
+ module Pricing
3
+
4
+ class << self
5
+ def included(klass)
6
+ klass.extend MacroMethods
7
+ end
8
+
9
+ def convert_to_cents(money_like)
10
+ case money_like
11
+ when String
12
+ money_like.gsub!(/[\$,\ ]/, '')
13
+ if money_like =~ /\./
14
+ money_like.gsub(/[\.]/,'').to_i
15
+ else
16
+ money_like.to_i * 100
17
+ end
18
+ when Money
19
+ money_like.cents.to_i
20
+ else
21
+ money_like.to_i
22
+ end
23
+ end
24
+
25
+ def convert_to_money(money_like)
26
+ Money.new(convert_to_cents(money_like))
27
+ end
28
+ end
29
+
30
+ module MacroMethods
31
+
32
+ def has_price(price_method, options = {})
33
+ include Qcontent::Pricing::InstanceMethods
34
+ default_value = options[:default] || Money.new(0)
35
+ attribute_name = options[:attribute] || "#{price_method}_cents"
36
+ override = options[:override] || Proc.new { false }
37
+ define_price_methods(price_method, attribute_name, default_value, &override)
38
+ end
39
+
40
+ protected
41
+
42
+ def define_price_methods(price_name, attribute_name, default_value, &override)
43
+ module_eval do
44
+ define_method(price_name) do
45
+ val = override.call(self)
46
+ return val if val
47
+ read_attribute(attribute_name.to_sym) ? Money.new(read_attribute(attribute_name.to_sym)) : default_value
48
+ end
49
+
50
+ define_method("#{price_name}=") do |new_price|
51
+ set_price(new_price, attribute_name.to_sym)
52
+ end
53
+
54
+ define_method("#{price_name}?") do
55
+ self.send(price_name) != default_value
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ module InstanceMethods
62
+
63
+ protected
64
+ def set_price(new_price, attribute)
65
+ write_attribute(attribute, Qcontent::Pricing.convert_to_cents(new_price))
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,48 @@
1
+ module Qcontent
2
+ module Published
3
+
4
+ def self.included(klass)
5
+ klass.module_eval do
6
+ def self.active_conditions
7
+ {}
8
+ end
9
+
10
+ def self.only_active(&block)
11
+ with_scope({:find => {:conditions => active_conditions}}, &block)
12
+ end
13
+
14
+ named_scope :active_only, lambda { {:conditions => active_conditions } }
15
+
16
+ end
17
+ return unless klass.column_names.include?('published_at')
18
+ klass.module_eval do
19
+
20
+ named_scope :published, :conditions => lambda { ["? > published_at", Time.now.utc] }
21
+ named_scope :recent, lambda {|how_many| {:order => 'published_at DESC', :limit => how_many || 3 }}
22
+
23
+ def published?
24
+ published_at && Time.now.utc > published_at
25
+ end
26
+ alias_method :is_published?, :published?
27
+ alias_method :is_published, :published?
28
+
29
+ def self.published_only
30
+ self.with_scope(:find => {:conditions => ["? > published_at", Time.now.utc]}) do
31
+ yield if block_given?
32
+ end
33
+ end
34
+
35
+ def self.most_recent(how_many = 1)
36
+ published.find(:all,:order => 'published_at DESC', :limit => how_many)
37
+ (!all.empty? && how_many == 1) ? all.first : all
38
+ end
39
+
40
+ def self.active_conditions
41
+ ["published_at <= ?", Time.now.utc]
42
+ end
43
+
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,45 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{qcontent}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Aaron Quint"]
9
+ s.date = %q{2009-03-21}
10
+ s.description = %q{Modules and Mixins for extending ActiveRecord models for content management systems}
11
+ s.email = ["aaron@quirkey.com"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "PostInstall.txt", "README.rdoc"]
13
+ s.files = ["History.txt", "LICENSE", "Manifest.txt", "PostInstall.txt", "README.rdoc", "Rakefile", "init.rb", "lib/qcontent.rb", "lib/qcontent/assets.rb", "lib/qcontent/dimension.rb", "lib/qcontent/extensions.rb", "lib/qcontent/pricing.rb", "lib/qcontent/published.rb", "qcontent.gemspec", "rails/init.rb", "test/test_dimension.rb", "test/test_helper.rb", "test/test_qcontent.rb"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://github.com/quirkey/qcontent}
16
+ s.post_install_message = %q{PostInstall.txt}
17
+ s.rdoc_options = ["--main", "README.rdoc"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{quirkey}
20
+ s.rubygems_version = %q{1.3.1}
21
+ s.summary = %q{Modules and Mixins for extending ActiveRecord models for content management systems}
22
+ s.test_files = ["test/test_dimension.rb", "test/test_helper.rb", "test/test_qcontent.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
26
+ s.specification_version = 2
27
+
28
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
29
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.2.0"])
30
+ s.add_runtime_dependency(%q<money>, [">= 2.0.0"])
31
+ s.add_development_dependency(%q<newgem>, [">= 1.2.3"])
32
+ s.add_development_dependency(%q<hoe>, [">= 1.8.0"])
33
+ else
34
+ s.add_dependency(%q<activesupport>, [">= 2.2.0"])
35
+ s.add_dependency(%q<money>, [">= 2.0.0"])
36
+ s.add_dependency(%q<newgem>, [">= 1.2.3"])
37
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
38
+ end
39
+ else
40
+ s.add_dependency(%q<activesupport>, [">= 2.2.0"])
41
+ s.add_dependency(%q<money>, [">= 2.0.0"])
42
+ s.add_dependency(%q<newgem>, [">= 1.2.3"])
43
+ s.add_dependency(%q<hoe>, [">= 1.8.0"])
44
+ end
45
+ end
@@ -0,0 +1,2 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'qcontent')
2
+
@@ -0,0 +1,108 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestDimension < Test::Unit::TestCase
4
+
5
+ context "Dimension" do
6
+ context "initializing" do
7
+ context "with two strings as arguments" do
8
+ setup do
9
+ @dimension = Qcontent::Dimension.new('400','300')
10
+ end
11
+
12
+ should "set width" do
13
+ assert_equal 400, @dimension.width
14
+ end
15
+
16
+ should "set height" do
17
+ assert_equal 300, @dimension.height
18
+ end
19
+ end
20
+
21
+ context "with two integers as arguments" do
22
+ setup do
23
+ @dimension = Qcontent::Dimension.new(400,300)
24
+ end
25
+
26
+ should "set width" do
27
+ assert_equal 400, @dimension.width
28
+ end
29
+
30
+ should "set height" do
31
+ assert_equal 300, @dimension.height
32
+ end
33
+ end
34
+
35
+ context "with an array" do
36
+ setup do
37
+ @dimension = Qcontent::Dimension.new(['400','300'])
38
+ end
39
+
40
+ should "set width" do
41
+ assert_equal 400, @dimension.width
42
+ end
43
+
44
+ should "set height" do
45
+ assert_equal 300, @dimension.height
46
+ end
47
+ end
48
+
49
+ context "with a hash" do
50
+ setup do
51
+ @dimension = Qcontent::Dimension.new({:width => 400, :height => 300})
52
+ end
53
+
54
+ should "set width" do
55
+ assert_equal 400, @dimension.width
56
+ end
57
+
58
+ should "set height" do
59
+ assert_equal 300, @dimension.height
60
+ end
61
+ end
62
+
63
+ context "with a single string" do
64
+ setup do
65
+ @dimension = Qcontent::Dimension.new('400')
66
+ end
67
+
68
+ should "set width" do
69
+ assert_equal 400, @dimension.width
70
+ end
71
+
72
+ should "set height" do
73
+ assert_equal nil, @dimension.height
74
+ end
75
+ end
76
+
77
+ context "with a single string with 'x' delimeter" do
78
+ setup do
79
+ @dimension = Qcontent::Dimension.new('400x300')
80
+ end
81
+
82
+ should "set width" do
83
+ assert_equal 400, @dimension.width
84
+ end
85
+
86
+ should "set height" do
87
+ assert_equal 300, @dimension.height
88
+ end
89
+ end
90
+
91
+ end
92
+
93
+ context "#to_s" do
94
+ should "join with and height" do
95
+ @dimension = Qcontent::Dimension.new(['400','300'])
96
+ assert_equal '400x300', @dimension.to_s
97
+ end
98
+ end
99
+
100
+ context "#to_a" do
101
+ should "return array with width, height" do
102
+ @dimension = Qcontent::Dimension.new(['400','300'])
103
+ assert_equal [400, 300], @dimension.to_a
104
+ end
105
+ end
106
+ end
107
+
108
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'stringio'
3
+ require 'test/unit'
4
+ require 'shoulda'
5
+ require 'mocha'
6
+
7
+ require File.dirname(__FILE__) + '/../lib/qcontent'
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestQcontent < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qcontent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Aaron Quint
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-21 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: activesupport
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.2.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: money
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: newgem
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.2.3
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: hoe
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.8.0
54
+ version:
55
+ description: Modules and Mixins for extending ActiveRecord models for content management systems
56
+ email:
57
+ - aaron@quirkey.com
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ extra_rdoc_files:
63
+ - History.txt
64
+ - Manifest.txt
65
+ - PostInstall.txt
66
+ - README.rdoc
67
+ files:
68
+ - History.txt
69
+ - LICENSE
70
+ - Manifest.txt
71
+ - PostInstall.txt
72
+ - README.rdoc
73
+ - Rakefile
74
+ - init.rb
75
+ - lib/qcontent.rb
76
+ - lib/qcontent/assets.rb
77
+ - lib/qcontent/dimension.rb
78
+ - lib/qcontent/extensions.rb
79
+ - lib/qcontent/pricing.rb
80
+ - lib/qcontent/published.rb
81
+ - qcontent.gemspec
82
+ - rails/init.rb
83
+ - test/test_dimension.rb
84
+ - test/test_helper.rb
85
+ - test/test_qcontent.rb
86
+ has_rdoc: true
87
+ homepage: http://github.com/quirkey/qcontent
88
+ post_install_message: PostInstall.txt
89
+ rdoc_options:
90
+ - --main
91
+ - README.rdoc
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: "0"
99
+ version:
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: "0"
105
+ version:
106
+ requirements: []
107
+
108
+ rubyforge_project: quirkey
109
+ rubygems_version: 1.3.1
110
+ signing_key:
111
+ specification_version: 2
112
+ summary: Modules and Mixins for extending ActiveRecord models for content management systems
113
+ test_files:
114
+ - test/test_dimension.rb
115
+ - test/test_helper.rb
116
+ - test/test_qcontent.rb