两种方法实现收藏或者点赞功能

收藏功能与点赞功能的实作十分类似,本文以购物车教程实作收藏功能为例。

方法一:

step1

一个用户可以收藏多个商品,一个商品可以被收藏很多次,因此这是多对多的关系。因此需要新增一个model,来当做product与suer的桥梁。$ rails g model collect user_id:integer product_id:integer,然后执行 rake db:migrate,然后为collect、user与product这三个model加上关联。

app/models/collect.rb
1
2
3
4
5
6
7
8
9

+ belongs_to :user
+ belongs_to :product
```

``` ruby app/models/product.rb

+ has_many :collects
+ has_many :collected_users, through: :collects, source: :user
app/models/user.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

+ has_many :collects
+ has_many :collected_products, through: :collects, source: :product

#加上是否收藏商品的判定
+ def is_collect_of?(product)
+ collected_products.include?(product)
+ end
```

#### step2
首先修改路由信息:
``` ruby config/routes.rb

+ resources :product do
+ member do
+ post :collect
+ post :uncollect
+ end
+ end

在controller里加上对应的method,

app/controllers/product_controllers.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14

+ def collect
+ @product = Product.find(params[:id])
+ current_user.collected_products << @product
+ flash[:notice] = "成功收藏商品"
+ redirect_to :back
+ end

+ def uncollect
+ @product = Product.find(params[:id])
+ currrent_user.collected_products.delete(@product)
+ flash[:warning] = "您已取消收藏该商品"
+ redirect_to :back
+ end

step3

在views中的相应位置加入收藏的显示

app/views/products/show.html.erb
1
2
3
4
5
6

+ <% if current_user && current_user.is_collect_of?(@product) %>
+ <%= link_to(“取消收藏”, uncollect_product_path(@product), :method => :post, class: "btn btn-danger btn-lg" )%>
+ <% else %>
+ <%= link_to("收藏“, collect_product_path(@product), :method => :post, class: "btn btn-danger btn-lg" )%>
+ <% end %>

方法二

step1

同样,终端执行 rails g model colloect, 编辑 db/migrate/XXXXXXXX_create_collects.rb

db/migrate/XXXXXXXX_create_collects.rb
1
2
3
4
5
6
7
8
9
  class CreateCollects < ActiveRecord::Migration[5.0]
def change
create_table :collects do |t|
+ t.integer :user_id, :index => true
+ t.integer :product_id, :index => true
t.timestamps
end
end
end

之后执行 rake db:migrate

编辑app/models/collect.rb,加上关联

app/models/collect.rb
1
2
+ belongs_to :user
+ belongs_to :product

编辑 app/models/product.rb,加上关联

app/models/product.rb
1
2
3
4
5
6
7
8
9
10
11
12
  + has_many :collects, :dependent => :destroy
+ had_many :collected_users, through: :collects, source: :user

+ def find_collect(user)
+ self.collects.where( :user_id => user.id).first
+ end
```

编辑 `app/model/user.rb`,加上关联
``` ruby app/models/user.rb
+ has_many :collects, :dependent => :destroy
+ has_many :collected_products, through: :collects, source: :product

step2

编辑路由信息

config/routes.rb
1
2
3
4
5
6
+ resource :products do
+ member do
+ post :collect
+ post :uncollect
+ end
+ end

在controller中添加:

app/controllers/product_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
+ def collect
+ @product = Product.find(params[:id])
+ unless @product.find_collect(cuurent_user)
+ Collect.create( :user => current_user, :product => @product)
+ flash[:notice] = "您已成功收藏该商品"
+ end
+ redirect_to :back
+ end

+ def uncollect
+ @product = Product.find(params[:id])
+ collect = @product.find_collect(current_user)
+ collect.destroy
+ flash[:warning] = "您已取消收藏该商品"
+ redirect_to :back
+ end

Step3

最后一歩,就是要在 app/views/products/show.html.erb中加上收藏的按钮

app/views/products/show.html.erb
1
2
3
4
5
6
7
8
9
……略
+ <% if current_user %>
+ <% if @product.find_collect(current_user)%>
+ <% =link_to("取消收藏", uncollect_product_path(@product), :method => :post, class: "btn btn-danger btn-lg")%>
+ <% else %>
+ <%= link_to("收藏", collect_product_path(@product), :method => :post, class: "btn btn-primary btn-lg")%>
+ <% end %>
+ <% end %>
……略

成果展示