one_touch 1.0.1 → 1.1.1
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.
- 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
|