one_touch 1.0.1 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/Gemfile +2 -3
- data/lib/one_touch/models/active_record_extension.rb +23 -12
- data/lib/one_touch/models/acts_as_favor.rb +4 -4
- data/lib/one_touch/models/as_favor_host.rb +5 -19
- data/lib/one_touch/models/as_favorable.rb +7 -12
- data/lib/one_touch/version.rb +1 -1
- data/readme.md +15 -11
- data/spec/fake_app.rb +1 -0
- data/spec/models/as_favorable_spec.rb +1 -6
- data/spec/spec_helper.rb +2 -2
- metadata +4 -5
- data/log/development.log +0 -0
data/.gitignore
CHANGED
data/Gemfile
CHANGED
@@ -8,7 +8,6 @@ gem 'rake'
|
|
8
8
|
gem 'rspec'
|
9
9
|
gem 'rspec-rails'
|
10
10
|
gem 'ruby-debug19'
|
11
|
-
gem 'rails'
|
12
|
-
gem '
|
13
|
-
# gem 'squeel' # add another version to support it and Rails3.1
|
11
|
+
gem 'rails'
|
12
|
+
gem 'squeel'
|
14
13
|
gem 'sqlite3', '~> 1.3.0', :group => :test
|
@@ -36,25 +36,37 @@ module OneTouch
|
|
36
36
|
unless opt[:no_default_relations]
|
37
37
|
if opt[:host_class_name].nil?
|
38
38
|
belongs_to :host, :polymorphic => true
|
39
|
-
host_relation_type = :polymorphic
|
40
|
-
if respond_to? method_name_of_host_klasses
|
41
|
-
send(method_name_of_host_klasses).each do |k|
|
42
|
-
k.to_s.constantize.rewrite_join_favors if k.to_s.constantize.respond_to? :rewrite_join_favors
|
43
|
-
end
|
44
|
-
end
|
39
|
+
self.host_relation_type = :polymorphic
|
45
40
|
else
|
46
41
|
belongs_to :host, :class_name => opt[:host_class_name]
|
47
|
-
host_relation_type = :single
|
42
|
+
self.host_relation_type = :single
|
48
43
|
end
|
49
44
|
if opt[:favorable_class_name].nil?
|
50
45
|
belongs_to :favorable, :polymorphic => true
|
51
|
-
favorable_relation_type = :polymorphic
|
46
|
+
self.favorable_relation_type = :polymorphic
|
52
47
|
else
|
53
48
|
belongs_to :favorable, :class_name => opt[:favorable_class_name]
|
54
|
-
favorable_relation_type = :single
|
49
|
+
self.favorable_relation_type = :single
|
55
50
|
end
|
56
51
|
end
|
57
52
|
|
53
|
+
# TODO:
|
54
|
+
# I should add more files to make here more clear
|
55
|
+
# Some methods should be include first
|
56
|
+
# And others should be include later
|
57
|
+
# This code should be in another file
|
58
|
+
#
|
59
|
+
if self.host_relation_type == :single
|
60
|
+
scope :host_as, lambda { |ahost| where(:host_id => ahost.id) }
|
61
|
+
else
|
62
|
+
scope :host_as, lambda { |ahost| where(:host_id => ahost.id, :host_type => ahost.class.name)}
|
63
|
+
end
|
64
|
+
if self.favorable_relation_type == :single
|
65
|
+
scope :favorable_as, lambda { |target| where(:favorable_id => target.id) }
|
66
|
+
else
|
67
|
+
scope :favorable_as, lambda { |target| where(:favorable_id => target.id, :favorable_type => target.class.name) }
|
68
|
+
end
|
69
|
+
|
58
70
|
if opt[:include_host_relation_module]
|
59
71
|
class_attribute :include_host_relation_module, :instance_writer => false
|
60
72
|
self.include_host_relation_module = true
|
@@ -68,6 +80,7 @@ module OneTouch
|
|
68
80
|
end
|
69
81
|
end
|
70
82
|
|
83
|
+
|
71
84
|
# Used in host class
|
72
85
|
# Ex:
|
73
86
|
# as_favor_host :klass => "OtherClass"
|
@@ -113,7 +126,7 @@ module OneTouch
|
|
113
126
|
|
114
127
|
favorable_klasses.each do |k|
|
115
128
|
klass = k.to_s.constantize
|
116
|
-
klass.send :include, HostRelation # host_relation model
|
129
|
+
klass.send :include, HostRelation # host_relation model was added to favorable klass
|
117
130
|
end
|
118
131
|
end
|
119
132
|
|
@@ -126,8 +139,6 @@ module OneTouch
|
|
126
139
|
self.favor_klass = opt[:klass]
|
127
140
|
self.favor_class = favor_klass.constantize
|
128
141
|
|
129
|
-
# favor_class.acts_as_favor :just_define_host_klasses => true unless favor_class.respond_to? :host_klasses
|
130
|
-
# favor.class.acts_as_favor
|
131
142
|
cattr_name = "#{cattr_name}_for_#{opt[:klass].underscore}".to_sym
|
132
143
|
unless ::ActiveRecord::Base.respond_to? cattr_name
|
133
144
|
::ActiveRecord::Base.class_attribute cattr_name, :instance_writer => false
|
@@ -20,7 +20,7 @@ module OneTouch
|
|
20
20
|
validate :context_should_match_favorable_type
|
21
21
|
validate :host_should_differ_favorable
|
22
22
|
|
23
|
-
scope :context_as, lambda { |
|
23
|
+
scope :context_as, lambda { |con| where(:context => con) }
|
24
24
|
|
25
25
|
# Generate build or destroy methods like:
|
26
26
|
# Favor.add_focus, Favor.del_focus
|
@@ -98,7 +98,7 @@ module OneTouch
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
-
# seems just used for
|
101
|
+
# seems just used for OneTouch::Relations module
|
102
102
|
def host_klasses
|
103
103
|
attr = "host_klasses_for_#{name.underscore}".to_sym
|
104
104
|
respond_to?(attr) ? send(attr) : []
|
@@ -133,7 +133,7 @@ module OneTouch
|
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
# how to reslove two or more hook
|
136
|
+
# TODO: how to reslove two or more hook
|
137
137
|
def context_relation_hook
|
138
138
|
context_relation.each do |key,contexts|
|
139
139
|
if contexts.include? context.to_sym
|
@@ -145,7 +145,7 @@ module OneTouch
|
|
145
145
|
|
146
146
|
def relation_oppose_hook(other_context)
|
147
147
|
oppose_context = other_context
|
148
|
-
oppose_favor=
|
148
|
+
oppose_favor= self.class.host_as(host).favorable_as(favorable).context_as(oppose_context)
|
149
149
|
oppose_favor.first.destroy if oppose_favor.presence
|
150
150
|
end
|
151
151
|
|
@@ -6,17 +6,9 @@ module OneTouch
|
|
6
6
|
|
7
7
|
class_attribute :default_context_in_host, :instance_writer => false
|
8
8
|
|
9
|
-
if favor_class.respond_to? :host_relation_type and favor_class.host_relation_type == :polymorphic
|
10
|
-
scope :join_favors, joins(:favors.type(self))
|
11
|
-
else
|
12
|
-
scope :join_favors, joins(:favors)
|
13
|
-
end
|
14
|
-
|
15
|
-
scope :favorable_is, lambda { |sth| where(:favors => { :favorable => sth } ) }
|
16
|
-
|
17
9
|
# One module may not only host but also favorable, ex: User model
|
18
|
-
# when User as favorable, defined a method called
|
19
|
-
scope :host_context_as, lambda { |context|
|
10
|
+
# when User as favorable, defined a method called favorable_context_as, here define another method to distinct the former
|
11
|
+
scope :host_context_as, lambda { |context| joins(:favors).where(favor_class.table_name.to_sym => { :context => context } ) }
|
20
12
|
|
21
13
|
if favor_class.respond_to? :host_relation_type # means favor class has load acts_as_favor
|
22
14
|
build_context_klass_methods
|
@@ -25,14 +17,8 @@ module OneTouch
|
|
25
17
|
|
26
18
|
module ClassMethods
|
27
19
|
|
28
|
-
# if favor_class.host_relation_type == :polymorphic, then this will be automated executed
|
29
|
-
def rewrite_join_favors
|
30
|
-
scope :join_favors, joins(:favors.type(self))
|
31
|
-
end
|
32
|
-
|
33
20
|
def favor_to(favorable,context=default_context_in_host)
|
34
|
-
|
35
|
-
favorable_is(favorable)
|
21
|
+
host_context_as(context) & Favor.favorable_as(favorable)
|
36
22
|
end
|
37
23
|
|
38
24
|
def after_load_acts_as_favor
|
@@ -44,7 +30,7 @@ module OneTouch
|
|
44
30
|
klasses.each do |klass|
|
45
31
|
method_name = "#{context}_#{klass.to_s.underscore.pluralize}".to_sym
|
46
32
|
define_method method_name do
|
47
|
-
klass.to_s.constantize.favored_by(self,context)
|
33
|
+
klass.to_s.constantize.favored_by(self,context) # TODO: here would cause problem, If klass did not respond_to favored_by? Need a test to prove it
|
48
34
|
end
|
49
35
|
end
|
50
36
|
end
|
@@ -55,7 +41,7 @@ module OneTouch
|
|
55
41
|
# find the favor to target with specific context
|
56
42
|
# return ARelation object
|
57
43
|
def find_favor(target,context)
|
58
|
-
favors.
|
44
|
+
favors & Favor.context_as(context).favorable_as(target)
|
59
45
|
end
|
60
46
|
|
61
47
|
# check favor exist or not
|
@@ -5,33 +5,28 @@ module OneTouch
|
|
5
5
|
included do
|
6
6
|
class_attribute :default_context_in_favorable, :instance_writer => false
|
7
7
|
|
8
|
-
scope :
|
9
|
-
|
10
|
-
scope :host_is, lambda { |someone| where(:be_favors => { :host => someone } ) }
|
11
|
-
scope :context_as, lambda { |context| where(:be_favors => { :context => context } ) if context.present? }
|
8
|
+
scope :favorable_context_as, lambda { |context| joins(:be_favors).where(favor_class.table_name.to_sym => { :context => context } ) } # if in the system there are two favor_klass, how to deal with
|
12
9
|
scope :group_by_favorable, group("#{favor_klass.downcase.pluralize}.favorable_id")
|
13
|
-
# scope :includes_favors_and_hosts, includes(:be_favors => :host)
|
14
10
|
|
15
|
-
end # included
|
11
|
+
end # End included
|
16
12
|
|
17
13
|
module ClassMethods
|
18
14
|
|
19
15
|
def allstars(context=default_context_in_favorable)
|
20
|
-
|
16
|
+
favorable_context_as(context).group_by_favorable.
|
21
17
|
select("count(*) as counter, #{self.table_name}.*").order("counter desc")
|
22
18
|
end
|
23
19
|
|
24
20
|
def favored_by(user,context = default_context_in_favorable)
|
25
|
-
|
26
|
-
host_is(user)
|
21
|
+
favorable_context_as(context) & Favor.host_as(user)
|
27
22
|
end
|
28
23
|
|
29
24
|
def unfavored_by(user,context = default_context_in_favorable)
|
30
25
|
favored_by_ids = favored_by(user,context).map(&:id).presence || [0]
|
31
|
-
where(
|
26
|
+
where("#{table_name}.id not in (?)", favored_by_ids)
|
32
27
|
end
|
33
28
|
|
34
|
-
end # ClassMethods
|
29
|
+
end # End ClassMethods
|
35
30
|
|
36
31
|
def favors_count(cont=default_context_in_favorable)
|
37
32
|
be_favors.context_as(cont).count
|
@@ -44,7 +39,7 @@ module OneTouch
|
|
44
39
|
end
|
45
40
|
|
46
41
|
def favored_by?(ahost, context= default_context_in_favorable)
|
47
|
-
be_favors.
|
42
|
+
(be_favors & Favor.host_as(ahost).context_as(context)).present?
|
48
43
|
end
|
49
44
|
|
50
45
|
private
|
data/lib/one_touch/version.rb
CHANGED
data/readme.md
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
### Intro
|
2
2
|
In webapp, many data is generated by just one click like focus someone, dislike some post.This gem make it easy.
|
3
3
|
|
4
|
-
These one click data most are relation data and managed in
|
4
|
+
These one click data most are relation data and was managed in single model in this gem. So we can analyze the relation data easily.
|
5
5
|
|
6
6
|
## Dependency
|
7
|
-
|
8
|
-
version ~> 2 will support Rails3.1 and need squeel
|
7
|
+
Rails > 3.0
|
9
8
|
|
10
9
|
## Usage
|
11
10
|
gem install one_touch
|
@@ -17,16 +16,17 @@ Then we define:
|
|
17
16
|
class User; as_favor_host; as_favorable; end;
|
18
17
|
class Post; as_favorable; end;
|
19
18
|
class Tag; as_favorable; end;
|
20
|
-
Make sure Favor has defined constants CONTEXT and CONTEXT_MATCH before acts_as_favor
|
21
|
-
The Favor columns depend on the relations you defined
|
22
|
-
In this case, it would be id, user_id, favorable_id, favorable_type, context.
|
23
|
-
Don't forget context column.
|
24
19
|
class Favor
|
25
20
|
CONTEXT = Set.new(%w[focus favorite follow agree oppose buy subscribe])
|
26
21
|
CONTEXT_MATCH = { :focus => [:Tag, :Post], :follow => [:User] }
|
27
|
-
|
28
22
|
acts_as_favor
|
29
23
|
end
|
24
|
+
|
25
|
+
Make sure Favor has defined constants CONTEXT and CONTEXT_MATCH before acts_as_favor.
|
26
|
+
The columns of table favors depend on the relations you defined.
|
27
|
+
In this case, it would be id, user_id, favorable_id, favorable_type and context.
|
28
|
+
Don't forget context column.
|
29
|
+
|
30
30
|
The generated relations between them are:
|
31
31
|
User has_many :favors, :class_name => "Favor", :as => :host
|
32
32
|
Post has_many :be_favors, :class_name => "Favor", :as => :favorable
|
@@ -40,6 +40,7 @@ You can define the relation by yourself.
|
|
40
40
|
belongs_to :favorable, :polymorphic => true
|
41
41
|
acts_as_favor :no_default_relations => true
|
42
42
|
end
|
43
|
+
|
43
44
|
Make sure the relation name are host and favorable, they can not be changed
|
44
45
|
|
45
46
|
Or you want Favor model to be another name, Bridge.
|
@@ -106,10 +107,13 @@ This means @user1 is more close to @user2 than @user3.Maybe the answers that @us
|
|
106
107
|
Because We create or delete data in one click. No Form Needed.
|
107
108
|
|
108
109
|
### TODO
|
109
|
-
Change the dependency meta_where to squeel and make it support Rails3.1
|
110
|
-
|
110
|
+
Change the dependency meta_where to squeel and make it support Rails3.1.
|
111
|
+
|
112
|
+
Add cache to favored_by, favor_to.
|
113
|
+
|
111
114
|
Add a generator to make install faster.
|
112
|
-
|
115
|
+
|
116
|
+
Add another gem to supply view and controller template.
|
113
117
|
|
114
118
|
### Abstract Requirement
|
115
119
|
Connect any two resource in one model.
|
data/spec/fake_app.rb
CHANGED
@@ -9,13 +9,8 @@ describe OneTouch::AsFavorable do
|
|
9
9
|
Tag.should respond_to(:allstars)
|
10
10
|
end
|
11
11
|
|
12
|
-
it "when context is nil, return all" do
|
13
|
-
all_tags = Tag.all
|
14
|
-
Tag.context_as(nil).should eq(all_tags)
|
15
|
-
end
|
16
|
-
|
17
12
|
it "first tag favors count should be 1" do
|
18
|
-
Tag.first.favors_count.should eq(1)
|
13
|
+
Tag.first.favors_count(:favorite).should eq(1)
|
19
14
|
end
|
20
15
|
|
21
16
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,9 +2,9 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
2
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
3
|
require 'rails'
|
4
4
|
require 'one_touch'
|
5
|
+
|
5
6
|
require File.join(File.dirname(__FILE__), 'fake_app')
|
6
|
-
require '
|
7
|
-
#require 'squeel'
|
7
|
+
# require 'squeel'
|
8
8
|
require 'rspec/rails'
|
9
9
|
require 'models/load_test_data'
|
10
10
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: one_touch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
12
|
+
date: 2011-11-17 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
16
|
-
requirement: &
|
16
|
+
requirement: &14408360 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
version: '3.0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *14408360
|
25
25
|
description: ! ' Make one click operation simple '
|
26
26
|
email:
|
27
27
|
- raykincoldxiao@gmail.com
|
@@ -43,7 +43,6 @@ files:
|
|
43
43
|
- lib/one_touch/models/relations.rb
|
44
44
|
- lib/one_touch/railtie.rb
|
45
45
|
- lib/one_touch/version.rb
|
46
|
-
- log/development.log
|
47
46
|
- one_touch.gemspec
|
48
47
|
- readme.md
|
49
48
|
- spec/fake_app.rb
|
data/log/development.log
DELETED
File without changes
|