2013-05-08 26 views
2

我試圖實現一個簡單的/不像函數。我在這裏看到的所有例子似乎都適用於ajax或jquery。我仍然是初學者,但我還沒有完全理解,我只想要一個簡單的解決方案。贊/不像沒有Ajax或jQuery on Rails

我的想法是,我有書,我有用戶。用戶可以喜歡書籍。所以我通過Like模型創建了一個多對多的關聯。 Like模型具有與book_id和user_id列相對應的數據庫。因此:

class Book < ActiveRecord::Base 
    has_many :likes 
    has_many :users, through: :likes 

class User < ActiveRecord::Base 
    has_many :likes 
    has_many :books, through: :likes 

class Like < ActiveRecord::Base 
    belongs_to :book 
    belongs_to :user 
end 

不幸的是,這是據我瞭解。我不知道如何利用這種關係來創造喜歡,並將它們與適當的書和用戶聯繫起來。

我的想法是,如果用戶不喜歡這本書,或者他沒有喜歡這本書,就會給用戶一個「喜歡」按鈕。所以基本上,我想有一些這個簡單:

<% if user likes? %> 

<div class="unlike_button"><%= link_to "Unlike", '#' %></div> 

<% else %> 

<div class="like_button"><%= link_to "Like", '#' %></div> 

<% end %> 

我用#存根,因爲我不知道應該用什麼樣的路線。但無論解決方案是什麼,我都希望它重定向到同一頁面,並提供「喜歡」或「不同」的Flash通知。 我已經有div背景圖像爲like_button和different_button類,這就是爲什麼我將它們實現爲圖像鏈接上面。

任何形式的指導或幫助,將深受讚賞。由於

UPDATE

我在這下面以下Bennick的指導,但我」,仍停留在軌道控制檯。我認爲如果我在控制檯中遇到錯誤,沒有任何意義。

至於建議,我想這在控制檯:

正如我已經有我做user = User.find(1)book = Book.find(1)

用戶,但在下一行like = Like.create(:user => user, :book => book)返回的羣衆分配錯誤。 Can't mass-assign protected attributes: book, user 我想這可能會幫助attr_accessible :book_id, :user_id在類似的模型,但我仍然得到錯誤。我錯過了什麼嗎?

解決

我終於得到它的工作!使用like = Like.create(:user => user.id, :book => book.id)

回答

6

好的,這裏有一些項目。我要帶你了堆棧模型 - >協會 - >控制器 - >視圖 - >路由器)。通常,當您設計一個Web應用程序時,您首先使用數據庫層並按照自己的方式工作。所以我們會在這裏做到這一點。

型號

這是你決定哪些數據庫對象,您需要和創建數據庫表來表示它們。如果你還沒有準備好,讀了Rails指南遷移: http://guides.rubyonrails.org/migrations.html

你的情況,這個設置將是合適的:

class Book < ActiveRecord::Base 
    attr_accessible :title 

    has_many :likes 
    has_many :users, through: :likes 
end 

class User < ActiveRecord::Base 
    attr_accessible :name 

    has_many :likes 
    has_many :books, through: :likes 
end 

class Like < ActiveRecord::Base 
    attr_accessible :book, :user 

    belongs_to :book 
    belongs_to :user 
end 

請注意,我們需要包括attr_accessible所以我們沒有得到任何質量 - 分配錯誤。請不要在Rails 4中這個安全功能已經進入控制器。有關這方面的看到這些或搜索內部網: http://blog.teamtreehouse.com/rails-4-strong-paremeters http://weblog.rubyonrails.org/2012/3/21/strong-parameters/

協會

你應該閱讀的Rails的協會指導: http://guides.rubyonrails.org/association_basics.html

這將在給你一個好主意數據庫對象(Active Record對象)如何相互交互。在你的問題中,你已經設置了這些。一旦建立關聯,Rails提供了許多用於訪問它們的方法。下面是一個例子軌控制檯會話:rails c

# Create a user 
user = User.create(:name => "Ryan") # I'm assuming User just requires a name for simplicity 
    => #<User id: 1, name: "Ryan"> 
# Create two a books 
book = Book.create(:title => "Game of Thrones") 
    => #<Book id: 1, title: "Game of Thrones"> 
book2 = Book.create(:title => "The Well-Grounded Rubyist") 
    => #<Book id: 2, title: "The Well-Grounded Rubyist"> 
# Create a two likes from the books and the user record 
like = Like.create(:user => user, :book => book) 
    => #<Like id: 1, user_id: 1, book_id: 1> 
like2 = Like.create(:user => user, :book => book2) 
    => #<Like id: 2, user_id: 1, book_id: 2> 
# Notice how the keys glue the associations 

# Query a user's likes 
user.likes.count 
    => 2 
user.likes 
    => #<ActiveRecord::Associations::CollectionProxy [#<Like id: 1, user_id: 1, book_id: 1>, #<Like id: 2, user_id: 1, book_id: 2>] 
# Query a user's books 
user.books 
    => #<ActiveRecord::Associations::CollectionProxy [#<Book id: 1, title: "Game of Thrones">, #<Book id: 1, title: "The Well-Grounded Rubyist">] 

有疑問時與軌道控制檯玩。你會從中學到很多東西。

控制器

爲了使最終用戶與數據庫交互的對象的控制是必要的,方便交流。再次閱讀相關的Rails指南:http://guides.rubyonrails.org/action_controller_overview.html 如果您現在還沒有猜到,我強烈推薦閱讀其中的大部分內容。

在你的事業,我們正在創建類似的對象所以讓我們做一個喜歡控制器:

rails g controller likes index

這將索引操作和查看文件創建控制器。

# app/controllers/likes_controller.rb 
class LikesController < ApplicationController 

    # This action will show our likes for a user. 
    # Lets assume you have an authentication system (ex Devise) that logs a user in and provides a `current_user` object 
    # GET /likes 
    def index 
    # Assign the logged in user to @user 
    @user = current_user 
    # Grab all of the books and put them into an array in @books 
    @books = Book.all 
    end 

    # This is our key action. We will use this action to create a Like 
    # POST /likes 
    def create 
    # Grab our book from the DB. Note that this syntax is for Rails 3.2 and below. Rails 4 uses something called Strong Parameters, but that is for another time. 
    book = Book.find(params[:book_id]) 
    # Create a like 
    Like.create(:book => book, :user => current_user) 
    # redirect back to the Like index page and assign a flash 
    redirect_to likes_path, :notice => "You just liked the book #{book.title}" 
    end 

    # here is where we will destroy a Like 
    # DELETE /likes/:id 
    def destroy 
    # Get the like form the DB 
    like = Like.find(params[:id]) 
    # destroy it 
    like.destroy 
    redirect_to likes_path, :notice => "You destroyed a like" 
    end 
end 

路由器

路由器就是連接外部的HTTP請求到控制器的動作。在你的情況下,所有你需要的是這樣的:

# config/routers.rb 
MyApp::Application.routes.draw do 

    resources :likes 

end 

這是Rails快捷方式,設置了7個標準的路線以及相關助手:

likes GET /likes(.:format)   likes#index 
      POST /likes(.:format)   likes#create 
new_like GET /likes/new(.:format)  likes#new 
edit_like GET /likes/:id/edit(.:format) likes#edit 
    like GET /likes/:id(.:format)  likes#show 
      PUT /likes/:id(.:format)  likes#update 
      DELETE /likes/:id(.:format)  likes#destroy 

請你幫個忙,並閱讀本指南:http://guides.rubyonrails.org/routing.html 它將解釋這些路線是什麼以及它們如何工作。 Rails像大多數現代Web開發世界一樣遵循REST。

查看

在你看來,你將需要一個形式爲用戶進行交互。這個表單將數據發送到應用程序,特別是發送到你的LikesController操作。

# app/views/likes/index.html.erb 

# show your flash messages 
<% flash.each do |name, msg| %> 
    <div class="alert <%= "alert-#{name}" %>"> 
    <%= msg %> 
    </div> 
<% end %> 

<h1>Books you may or may not like</h1> 
# For each book 
<% @books.each do |book| %> 
    <% unless @user.books.include?(book) %> # Prob want to move this into a User instance method 
    # Create a like form if the user does not have a like for this book 
    <%= form_tag likes_path do %> 
     <%= hidden_field_tag 'book_id', book.id %> 
     # Clicking this sends a request: POST /likes with params of: book_id=123 
     <%= submit_tag "Like this book", :class => "like_button" %> 
    <% end %> 
    <% else %> 
    # Find the like. I'll admit there is probably a better way to do this but it's getting past my bed time. 
    <% like = book.likes.where(:user_id => @user.id).first %> 
    # Destroy the like associated with this book and user 
    <div class="unlike_button"> 
     # Clicking this sends a request to: DELETE /likes/123 
     <%= link_to "destroy like", likes_path(like.id), :method => :delete %> 
    </div> 
    <% end %> 
<% end %> 

結論

我希望這給你一些指導。

在未來,請嘗試更具體的問題,因爲這個問題涉及大面積。我剛開始積極回饋,所以我可能已經完成了它。第一次出發時,我獲得了大量的免費指導和幫助。這是關於我回歸的時候了。

慢慢來,當您發現錯誤時,只需將其發佈到Google。你可能最終會遇到Stack Overflow問題。

乾杯!

+0

嗨貝尼克。非常感謝這個全面的迴應。我已經投票給你了。如果我還沒有停留在滑軌控制檯,我會投票作爲正確的答案。我剛剛編輯了這個問題,以反映我卡在哪裏。請查看 – muyiwamat 2013-05-09 13:44:41

+0

我終於開始工作了!使用'like = Like.create(:user => user.id,:book => book.id)'。非常感謝你的幫助。 – muyiwamat 2013-05-09 14:33:11

+1

@muyiwamat我很樂意幫忙。我還在Model部分下更新了我的答案。使用'attr_accessible:book_id,:user_id'的FYI將允許您通過模型ID進行分配。使用'attr_accessible:book,:user'將允許您通過完整模型對象進行分配。 – bennick 2013-05-09 14:43:35