tableless_model 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,9 +14,10 @@ Gem::Specification.new do |s|
14
14
  s.description = %q{A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object}
15
15
 
16
16
  s.add_dependency "validatable"
17
- s.add_development_dependency "minitest"
18
- s.add_development_dependency "ansi"
19
17
  s.add_development_dependency "sqlite3"
18
+ s.add_development_dependency "activerecord"
19
+ s.add_development_dependency "rspec"
20
+ s.add_development_dependency "timecop"
20
21
 
21
22
  s.rubyforge_project = "tableless_model"
22
23
 
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tableless_model
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ hash: 15
5
+ prerelease:
5
6
  segments:
6
7
  - 0
7
8
  - 0
8
- - 7
9
- version: 0.0.7
9
+ - 8
10
+ version: 0.0.8
10
11
  platform: ruby
11
12
  authors:
12
13
  - Vito Botta
@@ -14,7 +15,7 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2011-01-12 00:00:00 +00:00
18
+ date: 2011-07-24 00:00:00 +01:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
@@ -25,50 +26,68 @@ dependencies:
25
26
  requirements:
26
27
  - - ">="
27
28
  - !ruby/object:Gem::Version
29
+ hash: 3
28
30
  segments:
29
31
  - 0
30
32
  version: "0"
31
33
  type: :runtime
32
34
  version_requirements: *id001
33
35
  - !ruby/object:Gem::Dependency
34
- name: minitest
36
+ name: sqlite3
35
37
  prerelease: false
36
38
  requirement: &id002 !ruby/object:Gem::Requirement
37
39
  none: false
38
40
  requirements:
39
41
  - - ">="
40
42
  - !ruby/object:Gem::Version
43
+ hash: 3
41
44
  segments:
42
45
  - 0
43
46
  version: "0"
44
47
  type: :development
45
48
  version_requirements: *id002
46
49
  - !ruby/object:Gem::Dependency
47
- name: ansi
50
+ name: activerecord
48
51
  prerelease: false
49
52
  requirement: &id003 !ruby/object:Gem::Requirement
50
53
  none: false
51
54
  requirements:
52
55
  - - ">="
53
56
  - !ruby/object:Gem::Version
57
+ hash: 3
54
58
  segments:
55
59
  - 0
56
60
  version: "0"
57
61
  type: :development
58
62
  version_requirements: *id003
59
63
  - !ruby/object:Gem::Dependency
60
- name: sqlite3
64
+ name: rspec
61
65
  prerelease: false
62
66
  requirement: &id004 !ruby/object:Gem::Requirement
63
67
  none: false
64
68
  requirements:
65
69
  - - ">="
66
70
  - !ruby/object:Gem::Version
71
+ hash: 3
67
72
  segments:
68
73
  - 0
69
74
  version: "0"
70
75
  type: :development
71
76
  version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: timecop
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
72
91
  description: A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object
73
92
  email:
74
93
  - vito@botta.name
@@ -80,17 +99,19 @@ extra_rdoc_files: []
80
99
 
81
100
  files:
82
101
  - .gitignore
102
+ - .rspec
83
103
  - Gemfile
84
104
  - Gemfile.lock
85
- - README.rdoc
105
+ - README.md
86
106
  - Rakefile
87
107
  - lib/activerecord/base/class_methods.rb
108
+ - lib/activerecord/base/instance_methods.rb
88
109
  - lib/tableless_model.rb
89
110
  - lib/tableless_model/class_methods.rb
90
111
  - lib/tableless_model/instance_methods.rb
91
112
  - lib/tableless_model/version.rb
113
+ - spec/spec_helper.rb
92
114
  - spec/tableless_model_spec.rb
93
- - spec/test_helper.rb
94
115
  - tableless_model.gemspec
95
116
  has_rdoc: true
96
117
  homepage: https://github.com/vitobotta/tableless_model
@@ -106,6 +127,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
127
  requirements:
107
128
  - - ">="
108
129
  - !ruby/object:Gem::Version
130
+ hash: 3
109
131
  segments:
110
132
  - 0
111
133
  version: "0"
@@ -114,16 +136,17 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
136
  requirements:
115
137
  - - ">="
116
138
  - !ruby/object:Gem::Version
139
+ hash: 3
117
140
  segments:
118
141
  - 0
119
142
  version: "0"
120
143
  requirements: []
121
144
 
122
145
  rubyforge_project: tableless_model
123
- rubygems_version: 1.3.7
146
+ rubygems_version: 1.6.2
124
147
  signing_key:
125
148
  specification_version: 3
126
149
  summary: A serialisable and validatable table-less model with support for associations, useful to store settings, options, etc in a serialized form in a parent object
127
150
  test_files:
151
+ - spec/spec_helper.rb
128
152
  - spec/tableless_model_spec.rb
129
- - spec/test_helper.rb
data/README.rdoc DELETED
@@ -1,170 +0,0 @@
1
- = Tableless Model
2
-
3
- This is an extended Hash that has a defined collection of method-like attributes, and only these attributes can be set or read from the hash.
4
- Optionally, you can also set default values and enforce data types for these attributes.
5
-
6
- Tableless Model behaves in a similar way to normal ActiveRecord models in that it also supports validations and can be useful, for example, to reduce database complexity in some cases, by removing associations and therefore tables.
7
-
8
- In particular, by using Tableless Model, you could save tables whenever you have one to one associations between a parent model and a child model containing options, settings, debugging information or any other collection of attributes that belongs uniquely to a single parent object.
9
-
10
- Removing database tables also means reducing the number of queries to fetch associations, therefore it can also help a little bit with performance.
11
-
12
-
13
- == Installation
14
-
15
- Tableless Model is available as a Rubygem:
16
-
17
- gem install tableless_model
18
-
19
- (current version: 0.0.7)
20
-
21
-
22
- == Usage
23
-
24
- For example's sake, say we have these two models:
25
-
26
- 1)
27
-
28
- class Page < ActiveRecord::Base
29
-
30
- # having columns such as id, title, etc
31
-
32
- has_one :seo_options
33
-
34
- end
35
-
36
- 2)
37
-
38
- class SeoOptions < ActiveRecord::Base
39
-
40
- set_table_name "seo_options"
41
-
42
- # having columns such as id, title_tag, meta_description, meta_keywords,
43
- # noindex, nofollow, noarchive, page_id
44
-
45
- belongs_to :page
46
-
47
- end
48
-
49
-
50
- So that each instance of Page has its own SEO options, and these options/settings only belong to a page, so we have a one to one association, and our database will have the tables "pages", and "seo_options".
51
-
52
- Using Tableless Model, we could remove the association and the table seo_options altogether, by storing those options in a column of the pages table, in a YAML-serialized form. So the models become:
53
-
54
-
55
- 1)
56
-
57
- class Page < ActiveRecord::Base
58
-
59
- # having columns such as id, title, seo, etc
60
-
61
- has_tableless :seo => SeoOptions
62
-
63
- end
64
-
65
- 2)
66
-
67
- class SeoOptions < ActiveRecord::TablelessModel
68
-
69
- attribute :title_tag, :type => :string, :default => "default title tag"
70
- attribute :meta_description, :type => :string, :default => ""
71
- attribute :meta_keywords, :type => :string, :default => ""
72
- attribute :noindex, :type => :boolean, :default => false
73
- attribute :nofollow, :type => :boolean, :default => false
74
- attribute :noarchive, :type => :boolean, :default => false
75
-
76
- end
77
-
78
-
79
- That's it.
80
-
81
- When you now create an instance of SeoOptions, you can get and set its attributes as you would do with a normal model:
82
-
83
- seo_options = SeoOptions.new
84
- => <#SeoOptions meta_description="" meta_keywords="" noarchive=false nofollow=false noindex=false
85
- title_tag="default title tag">
86
-
87
- seo_options.title_tag
88
- => "default title tag"
89
-
90
- seo_options.title_tag = "new title tag"
91
- => "new title tag"
92
-
93
- Note that inspect shows the properties of the Tableless Model in the same way it does for ActiveRecord models.
94
- Of course, you can also override the default values for the attributes when creating a new instance:
95
-
96
- seo_options = SeoOptions.new( :title_tag => "a different title tag" )
97
- => <#SeoOptions meta_description="" meta_keywords="" noarchive=false nofollow=false noindex=false
98
- title_tag="a different title tag">
99
-
100
- Now, if you have used the has_tabless macro in the parent class, Page, each instance of Page will store directly its YAML-serialized SEO settings in the column named "seo".
101
-
102
- page = Page.new
103
-
104
- page.seo
105
- => <#SeoOptions meta_description="" meta_keywords="" noarchive=false nofollow=false noindex=false
106
- title_tag="default title tag">
107
-
108
- page.seo.title_tag = "changed title tag"
109
- => <#SeoOptions meta_description="" meta_keywords="" noarchive=false nofollow=false noindex=false
110
- title_tag="changed title tag">
111
-
112
-
113
- And this is how the content of the serialized column would look like in the database if you saved the changes as in the example
114
-
115
- --- !map:SeoOptions
116
- noarchive: false
117
- meta_description:
118
- meta_keywords:
119
- nofollow: false
120
- title_tag: "changed title tag"
121
- noindex: false
122
-
123
-
124
- == Validations
125
-
126
- Tableless Model uses the Validatable gem to support validations methods and callbacks (such as "after_validation").
127
- Note: it currently uses the Rails 2.x syntax only.
128
-
129
- Example:
130
-
131
-
132
- class SeoOptions < ActiveRecord::TablelessModel
133
-
134
- attribute :title_tag, :type => :string, :default => ""
135
- attribute :meta_description, :type => :string, :default => ""
136
- attribute :meta_keywords, :type => :string, :default => ""
137
- attribute :noindex, :type => :boolean, :default => false
138
- attribute :nofollow, :type => :boolean, :default => false
139
- attribute :noarchive, :type => :boolean, :default => false
140
-
141
- validates_presence_of :meta_keywords
142
-
143
- end
144
-
145
-
146
- Testing:
147
-
148
- x = SeoOptionsSettings.new
149
- => <#SeoOptions meta_description="" meta_keywords="" noarchive=false nofollow=false noindex=false
150
- title_tag="">
151
-
152
- x.valid?
153
- => false
154
-
155
- x.meta_keywords = "test"
156
- => "test"
157
-
158
- x.valid?
159
- => true
160
-
161
-
162
- == TODO
163
-
164
- * Support for associations
165
-
166
-
167
- == Authors
168
-
169
- * Vito Botta ( http://vitobotta.com )
170
-
data/spec/test_helper.rb DELETED
@@ -1,157 +0,0 @@
1
- require 'rubygems'
2
- gem "minitest"
3
- require 'minitest/autorun'
4
-
5
- require 'ansi'
6
-
7
- class MiniTest::Unit
8
- include ANSI::Code
9
-
10
- PADDING_SIZE = 4
11
-
12
- def run(args = [])
13
- @verbose = true
14
-
15
- filter = if args.first =~ /^(-n|--name)$/ then
16
- args.shift
17
- arg = args.shift
18
- arg =~ /\/(.*)\// ? Regexp.new($1) : arg
19
- else
20
- /./ # anything - ^test_ already filtered by #tests
21
- end
22
-
23
- @@out.puts "Loaded suite #{$0.sub(/\.rb$/, '')}\nStarted"
24
-
25
- start = Time.now
26
- run_test_suites filter
27
-
28
- @@out.puts
29
- @@out.puts "Finished in #{'%.6f' % (Time.now - start)} seconds."
30
-
31
- @@out.puts
32
-
33
- @@out.print "%d tests, " % test_count
34
- @@out.print "%d assertions, " % assertion_count
35
- @@out.print red { "%d failures, " % failures }
36
- @@out.print yellow { "%d errors, " % errors }
37
- @@out.puts cyan { "%d skips" % skips}
38
-
39
- return failures + errors if @test_count > 0 # or return nil...
40
- end
41
-
42
- # Overwrite #run_test_suites so that it prints out reports
43
- # as errors are generated.
44
- def run_test_suites(filter = /./)
45
- @test_count, @assertion_count = 0, 0
46
- old_sync, @@out.sync = @@out.sync, true if @@out.respond_to? :sync=
47
-
48
- TestCase.test_suites.each do |suite|
49
- test_cases = suite.test_methods.grep(filter)
50
- if test_cases.size > 0
51
- @@out.print "\n#{suite}:\n"
52
- end
53
-
54
- test_cases.each do |test|
55
- inst = suite.new test
56
- inst._assertions = 0
57
-
58
- t = Time.now
59
-
60
- @broken = nil
61
-
62
- @@out.print(case inst.run(self)
63
- when :pass
64
- @broken = false
65
- green { pad_with_size "PASS" }
66
- when :error
67
- @broken = true
68
- yellow { pad_with_size "ERROR" }
69
- when :fail
70
- @broken = true
71
- red { pad_with_size "FAIL" }
72
- when :skip
73
- @broken = false
74
- cyan { pad_with_size "SKIP" }
75
- end)
76
-
77
-
78
- # @@out.print " #{test.humanize.gsub(/Test\s\d+\s(.*)/,"\\1")} "
79
- @@out.print " #{test} "
80
- @@out.print " (%.2fs) " % (Time.now - t)
81
-
82
- if @broken
83
- @@out.puts
84
-
85
- report = @report.last
86
- @@out.puts pad(report[:message], 10)
87
- trace = MiniTest::filter_backtrace(report[:exception].backtrace).first
88
- @@out.print pad(trace, 10)
89
-
90
- @@out.puts
91
- end
92
-
93
- @@out.puts
94
- @test_count += 1
95
- @assertion_count += inst._assertions
96
- end
97
- end
98
- @@out.sync = old_sync if @@out.respond_to? :sync=
99
- [@test_count, @assertion_count]
100
- end
101
-
102
- def pad(str, size=PADDING_SIZE)
103
- " " * size + str
104
- end
105
-
106
- def pad_with_size(str)
107
- pad("%5s" % str)
108
- end
109
-
110
- # Overwrite #puke method so that is stores a hash
111
- # with :message and :exception keys.
112
- def puke(klass, meth, e)
113
- result = nil
114
- msg = case e
115
- when MiniTest::Skip
116
- @skips += 1
117
- result = :skip
118
- e.message
119
- when MiniTest::Assertion
120
- @failures += 1
121
- result = :fail
122
- e.message
123
- else
124
- @errors += 1
125
- result = :error
126
- "#{e.class}: #{e.message}\n"
127
- end
128
-
129
- @report << {:message => msg, :exception => e}
130
- result
131
- end
132
-
133
-
134
- class TestCase
135
- # Overwrite #run method so that is uses symbols
136
- # as return values rather than characters.
137
- def run(runner)
138
- result = :pass
139
- begin
140
- @passed = nil
141
- self.setup
142
- self.send self.__name__
143
- @passed = true
144
- rescue Exception => e
145
- @passed = false
146
- result = runner.puke(self.class, self.__name__, e)
147
- ensure
148
- begin
149
- self.teardown
150
- rescue Exception => e
151
- result = runner.puke(self.class, self.__name__, e)
152
- end
153
- end
154
- result
155
- end
156
- end
157
- end