2013-05-08 42 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