friendly-attributes 0.7.1.1 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,45 @@
1
+ # rcov generated
2
+ coverage
3
+
4
+ # rdoc generated
5
+ rdoc
6
+
7
+ # yard generated
8
+ doc
9
+ .yardoc
10
+
11
+ # bundler
12
+ .bundle
13
+
14
+ # jeweler generated
15
+ pkg
16
+
17
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
18
+ #
19
+ # * Create a file at ~/.gitignore
20
+ # * Include files you want ignored
21
+ # * Run: git config --global core.excludesfile ~/.gitignore
22
+ #
23
+ # After doing this, these files will be ignored in all your git projects,
24
+ # saving you from having to 'pollute' every project you touch with them
25
+ #
26
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
27
+ #
28
+ # For MacOS:
29
+ #
30
+ #.DS_Store
31
+ #
32
+ # For TextMate
33
+ #*.tmproj
34
+ #tmtags
35
+ #
36
+ # For emacs:
37
+ #*~
38
+ #\#*
39
+ #.\#*
40
+ #
41
+ # For vim:
42
+ #*.swp
43
+ spec/config.yml
44
+ log
45
+ friendly-attributes.tmproj
@@ -0,0 +1 @@
1
+ ruby-1.9.3
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ before_script:
5
+ - mysql -e 'create database friendly_attributes_test;'
6
+ - cp spec/config.sample.yml spec/config.yml
@@ -0,0 +1 @@
1
+ --no-private lib/**/*.rb - CHANGELOG.md LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,45 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ friendly-attributes (0.7.2)
5
+ activerecord (~> 2.3.18)
6
+ ihoka-friendly (~> 0.7.0)
7
+ memcached (~> 0.20.1)
8
+ yajl-ruby (~> 0.7.7)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ activerecord (2.3.18)
14
+ activesupport (= 2.3.18)
15
+ activesupport (2.3.18)
16
+ database_cleaner (0.5.2)
17
+ diff-lcs (1.1.3)
18
+ ihoka-friendly (0.7.0)
19
+ activesupport (~> 2.3.18)
20
+ rufus-json (~> 0.2.3)
21
+ sequel (~> 3.16.0)
22
+ will_paginate (~> 2.3.15)
23
+ memcached (0.20.1)
24
+ mysql (2.8.1)
25
+ rspec (2.5.0)
26
+ rspec-core (~> 2.5.0)
27
+ rspec-expectations (~> 2.5.0)
28
+ rspec-mocks (~> 2.5.0)
29
+ rspec-core (2.5.2)
30
+ rspec-expectations (2.5.0)
31
+ diff-lcs (~> 1.1.2)
32
+ rspec-mocks (2.5.0)
33
+ rufus-json (0.2.7)
34
+ sequel (3.16.0)
35
+ will_paginate (2.3.16)
36
+ yajl-ruby (0.7.9)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ database_cleaner (~> 0.5.0)
43
+ friendly-attributes!
44
+ mysql (~> 2.8.1)
45
+ rspec (~> 2.5.0)
data/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Friendly Attributes
2
2
 
3
+ [![Build Status](https://travis-ci.org/ihoka/friendly-attributes.png)](https://travis-ci.org/ihoka/friendly-attributes)
4
+
5
+
3
6
  Extend your ActiveRecord models with attributes dynamically, without any schema migrations.
4
7
 
5
8
  ## Description
@@ -0,0 +1,25 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core'
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = FileList['spec/**/*_spec.rb']
7
+ end
8
+
9
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
10
+ spec.pattern = FileList['spec/**/*_spec.rb']
11
+ spec.rcov = true
12
+ spec.rcov_opts = %w{-I spec:lib --exclude gems\/,spec\/}
13
+ end
14
+
15
+ task :default => :spec
16
+
17
+ require 'rdoc/task'
18
+ Rake::RDocTask.new do |rdoc|
19
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
20
+
21
+ rdoc.rdoc_dir = 'rdoc'
22
+ rdoc.title = "friendly-attributes #{version}"
23
+ rdoc.rdoc_files.include('README*')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.7.2
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{friendly-attributes}
7
+ s.version = "0.7.1.1"
8
+
9
+ s.authors = ["Istvan Hoka"]
10
+ s.date = %q{2011-04-10}
11
+ s.description = %q{Pattern to add fields to ActiveRecord models, using an associated document, without needing schema migrations.}
12
+ s.email = %q{istvan.hoka@gmail.com}
13
+ s.homepage = %q{http://github.com/ihoka/friendly-attributes}
14
+ s.licenses = ["MIT"]
15
+ s.summary = %q{Extend ActiveRecord models using Friendly ORM delegate models}
16
+ s.version = File.read(File.dirname(__FILE__) + '/VERSION')
17
+
18
+ s.add_development_dependency 'mysql', '~> 2.8.1'
19
+ s.add_development_dependency 'rspec', '~> 2.5.0'
20
+ s.add_development_dependency 'database_cleaner', '~> 0.5.0'
21
+ s.add_dependency 'ihoka-friendly', '~> 0.7.0'
22
+ s.add_dependency 'activerecord', '~> 2.3.18'
23
+ s.add_dependency 'yajl-ruby', '~> 0.7.7'
24
+ s.add_dependency 'memcached', '~> 0.20.1'
25
+
26
+ s.files = `git ls-files`.split("\n")
27
+ s.test_files = `git ls-files -- spec/*`.split("\n")
28
+ s.require_paths = ["lib"]
29
+ end
30
+
@@ -0,0 +1,6 @@
1
+ test:
2
+ :adapter: "mysql"
3
+ :host: "localhost"
4
+ :user: "root"
5
+ :password:
6
+ :database: "friendly_attributes_test"
@@ -0,0 +1,122 @@
1
+ require 'spec_helper'
2
+
3
+ describe FriendlyAttributes::Base do
4
+ use_database_cleanup
5
+
6
+ let(:friendly_model) {
7
+ Class.new(FriendlyAttributes::Base) do
8
+ cattr_accessor :active_record_key
9
+ end.tap { |c| c.active_record_key = active_record_key }
10
+ }
11
+ let(:active_record_key) { :ar_id }
12
+ let(:details) { mock(FriendlyAttributes::Base) }
13
+
14
+ describe ".find_or_build_by_active_record_id" do
15
+
16
+ context "when the record does not exist" do
17
+ before(:each) do
18
+ friendly_model.should_receive(:first).with(:ar_id => 42).and_return(nil)
19
+ end
20
+
21
+ it "builds a new record with the active_record_id" do
22
+ friendly_model.should_receive(:new).with(:ar_id => 42).and_return(details)
23
+ friendly_model.find_or_build_by_active_record_id(42).should == details
24
+ end
25
+
26
+ it "with options present, it builds a new record with the options and active_record_id" do
27
+ friendly_model.should_receive(:new).with(:ar_id => 42, :foo => "foo").and_return(details)
28
+ friendly_model.find_or_build_by_active_record_id(42, :foo => "foo").should == details
29
+ end
30
+ end
31
+
32
+ context "when the record exists" do
33
+ it "finds the record" do
34
+ friendly_model.should_receive(:first).with(:ar_id => 42).and_return(details)
35
+ friendly_model.find_or_build_by_active_record_id(42).should == details
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "#write_active_record_id" do
41
+ let(:friendly_instance) { friendly_model.new }
42
+
43
+ it "sets the active_record_id using the configured attribute writer" do
44
+ friendly_instance.should_receive(:"#{active_record_key}=").with(42).and_return(42)
45
+ friendly_instance.write_active_record_id(42).should == 42
46
+ end
47
+ end
48
+
49
+ describe "#read_active_record_id" do
50
+ let(:friendly_instance) { friendly_model.new }
51
+
52
+ it "sets the active_record_id using the configured attribute writer" do
53
+ friendly_instance.should_receive(active_record_key).and_return(42)
54
+ friendly_instance.read_active_record_id.should == 42
55
+ end
56
+ end
57
+
58
+ describe "#update_if_changed_with_model" do
59
+ let(:friendly_instance) { friendly_model.new }
60
+
61
+ before(:each) do
62
+ friendly_instance.stub(:save => false, :changed? => false, :read_active_record_id => 42)
63
+ end
64
+
65
+ context "when the active_record_id is not set" do
66
+ before(:each) do
67
+ friendly_instance.should_receive(:read_active_record_id).and_return(nil)
68
+ end
69
+
70
+ it "sets the active_record_id" do
71
+ friendly_instance.should_receive(:write_active_record_id).with(42)
72
+ friendly_instance.update_if_changed_with_model(42)
73
+ end
74
+ end
75
+
76
+ context "when the active_record_id is set" do
77
+ before(:each) do
78
+ friendly_instance.should_receive(:read_active_record_id).and_return(42)
79
+ end
80
+
81
+ it "does not reset the active_record_id" do
82
+ friendly_instance.should_not_receive(:write_active_record_id)
83
+ friendly_instance.update_if_changed_with_model(42)
84
+ end
85
+ end
86
+
87
+ context "when changed" do
88
+ before(:each) do
89
+ friendly_instance.should_receive(:changed?).and_return(true)
90
+ end
91
+
92
+ it "saves the record" do
93
+ friendly_instance.should_receive(:save).and_return(true)
94
+ friendly_instance.update_if_changed_with_model(42).should be_true
95
+ end
96
+ end
97
+
98
+ context "when not changed" do
99
+ before(:each) do
100
+ friendly_instance.should_receive(:changed?).and_return(false)
101
+ end
102
+
103
+ it "saves the record" do
104
+ friendly_instance.should_not_receive(:save)
105
+ friendly_instance.update_if_changed_with_model(42).should be_false
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#attributes" do
111
+ let(:details) { UserDetails.create(attributes) }
112
+ let(:attributes) { { :name => "Foo", :birth_year => 1970, :shoe_size => 42, :subscribed => true, UserDetails.active_record_key => 55 } }
113
+
114
+ it "returns a hash of all the model's attributes" do
115
+ actual = details.attributes
116
+ actual.should include(attributes)
117
+ actual[:created_at].should be_an_instance_of(Time)
118
+ actual[:updated_at].should be_an_instance_of(Time)
119
+ actual[:id].should be_an_instance_of(Friendly::UUID)
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,124 @@
1
+ require 'spec_helper'
2
+
3
+ describe FriendlyAttributes::ClassMethods do
4
+ let(:friendly_model) { mock_friendly_model }
5
+ let(:ar_model) {
6
+ Class.new {
7
+ include ActiveRecordFake
8
+ extend FriendlyAttributes::ClassMethods
9
+ }
10
+ }
11
+
12
+ let(:details_delegator) { mock(FriendlyAttributes::DetailsDelegator) }
13
+
14
+ class FakeUploader; end
15
+
16
+ describe ".friendly_details" do
17
+ let(:attributes) do
18
+ {
19
+ String => :foo,
20
+ Integer => [:bar, :baz]
21
+ }
22
+ end
23
+
24
+ before(:each) do
25
+ details_delegator.stub(:setup_delegated_attributes)
26
+ end
27
+
28
+ context "with an initializer block" do
29
+ def yielded_inside(instance)
30
+ @yielded_instance = instance
31
+ end
32
+
33
+ let(:initializer) do
34
+ example = self
35
+
36
+ proc {
37
+ example.yielded_inside(self)
38
+ }
39
+ end
40
+
41
+ it "instance_evals the initializer block on the DetailsDelegator instance" do
42
+ FriendlyAttributes::DetailsDelegator.
43
+ should_receive(:new).
44
+ with(friendly_model, ar_model, attributes, {}).
45
+ and_return(details_delegator)
46
+
47
+ ar_model.friendly_details(friendly_model, attributes, &initializer).should == details_delegator
48
+ @yielded_instance.should == details_delegator
49
+ end
50
+ end
51
+
52
+ context "with attributes and options" do
53
+ let(:options) { { :active_record_key => :user_id } }
54
+
55
+ before(:each) do
56
+ FriendlyAttributes::DetailsDelegator.stub(:new => details_delegator)
57
+ end
58
+
59
+ def do_details
60
+ ar_model.friendly_details(friendly_model, attributes, options).should == details_delegator
61
+ end
62
+
63
+ it "instantiates a new DetailsDelegator" do
64
+ FriendlyAttributes::DetailsDelegator.should_receive(:new).with(friendly_model, ar_model, attributes, options).and_return(details_delegator)
65
+ do_details
66
+ end
67
+
68
+ it "sets up the delegated attributes" do
69
+ details_delegator.should_receive(:setup_delegated_attributes)
70
+ do_details
71
+ end
72
+ end
73
+
74
+ context "without a block" do
75
+ it "instantiates a new DetailsDelegator" do
76
+ FriendlyAttributes::DetailsDelegator.should_receive(:new).with(friendly_model, ar_model, attributes, {}).and_return(details_delegator)
77
+ ar_model.friendly_details(friendly_model, attributes).should == details_delegator
78
+ end
79
+ end
80
+ end
81
+
82
+ describe ".friendly_mount_uploader" do
83
+ let(:foo_value) { mock("Friendly attribute value") }
84
+
85
+ before(:each) do
86
+ ar_model.stub(:mount_uploader => nil)
87
+
88
+ foo = foo_value
89
+
90
+ ar_model.class_eval do
91
+ define_method(:read_friendly_attribute) do |attribute|
92
+ attribute.should == :foo
93
+ foo
94
+ end
95
+
96
+ define_method(:write_friendly_attribute) do |attribute, value|
97
+ value.tap do
98
+ attribute.should == :foo
99
+ value.should == foo
100
+ end
101
+ end
102
+ end
103
+ end
104
+
105
+ it "mounts the uploader" do
106
+ ar_model.should_receive(:mount_uploader).with(:foo, FakeUploader)
107
+ ar_model.friendly_mount_uploader :foo, FakeUploader
108
+ end
109
+
110
+ it "aliases #read_friendly_attribute to #read_uploader" do
111
+ ar_model.friendly_mount_uploader :foo, FakeUploader
112
+ ar_object = ar_model.new
113
+
114
+ ar_object.read_uploader(:foo).should == foo_value
115
+ end
116
+
117
+ it "aliases #read_friendly_attribute to #read_uploader" do
118
+ ar_model.friendly_mount_uploader :foo, FakeUploader
119
+ ar_object = ar_model.new
120
+
121
+ ar_object.write_uploader(:foo, foo_value).should == foo_value
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+
3
+ describe FriendlyAttributes::Configuration do
4
+ subject { configuration }
5
+
6
+ let(:configuration) { FriendlyAttributes::Configuration.new(active_record_model) }
7
+ let(:active_record_model) { User }
8
+
9
+ describe "#initialize" do
10
+ its(:model) { should == active_record_model }
11
+ its(:details_delegators) { should == [] }
12
+ its(:attributes) { should == {} }
13
+ end
14
+
15
+ describe "#add" do
16
+ let(:delegator) { mock(FriendlyAttributes::DetailsDelegator, :delegated_attributes => delegated_attributes, :friendly_model => UserDetails) }
17
+ let(:delegated_attributes) { { :foo => Integer, :bar => String } }
18
+
19
+ it "adds a delegator to the details_delegators collection" do
20
+ configuration.add(delegator)
21
+ configuration.details_delegators.should == [delegator]
22
+ end
23
+ end
24
+
25
+ describe "#add_attribute" do
26
+ it "adds the attribute to the attributes collection" do
27
+ configuration.add_attribute(:foo, UserDetails)
28
+ configuration.attributes.should == { :foo => UserDetails }
29
+ end
30
+ end
31
+
32
+ describe "Configuration with delegators added" do
33
+ let(:friendly_models) { [UserDetails, UserSecondDetails] }
34
+ let(:delegated_attributes) {
35
+ {
36
+ UserDetails => { :foo => Integer, :bar => String },
37
+ UserSecondDetails => { :baz => Date }
38
+ }
39
+ }
40
+ let(:details_delegators) {
41
+ friendly_models.map do |fm|
42
+ mock(FriendlyAttributes::DetailsDelegator,
43
+ :friendly_model => fm,
44
+ :delegated_attributes => delegated_attributes[fm])
45
+ end
46
+ }
47
+
48
+ before(:each) do
49
+ details_delegators.each do |delegator|
50
+ configuration.add(delegator)
51
+ end
52
+ end
53
+
54
+ describe "#model_for_attribute" do
55
+ it "returns the FriendlyAttributes model associated with the attribute" do
56
+ configuration.add_attribute(:foo, UserDetails)
57
+ configuration.model_for_attribute(:foo).should == UserDetails
58
+ end
59
+ end
60
+
61
+ describe "#friendly_models" do
62
+ its(:friendly_models) { should == friendly_models }
63
+ end
64
+
65
+ describe "#map_models" do
66
+ let(:map_model_map) {
67
+ {}.tap do |h|
68
+ friendly_models.each_with_index do |m, i|
69
+ h[m] = i
70
+ end
71
+ end
72
+ }
73
+
74
+ it "maps over the friendly models" do
75
+ configuration.map_models do |model|
76
+ map_model_map[model]
77
+ end.sort.should == map_model_map.values.sort
78
+ end
79
+ end
80
+
81
+ describe "#each_model" do
82
+ let(:each_model_map) {
83
+ {}.tap do |h|
84
+ friendly_models.each_with_index do |m, i|
85
+ h[m] = i
86
+ end
87
+ end
88
+ }
89
+
90
+ it "iterates over the friendly models" do
91
+ result = []
92
+ configuration.each_model do |model|
93
+ result << each_model_map[model]
94
+ end
95
+ result.sort.should == each_model_map.values.sort
96
+ end
97
+ end
98
+ end
99
+ end