喜欢/不喜欢没有Ajax或jQuery on Rails

muy*_*mat 2 jquery ruby-on-rails ruby-on-rails-3

我正在尝试实现一个简单的喜欢/不同的功能.我在这里看到的所有例子似乎都适用于ajax或jquery.我还是初学者,我还没有完全理解,我只想要一个简单的解决方案.

我的想法是,我有书,我有用户.用户可以喜欢书籍.所以我通过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
Run Code Online (Sandbox Code Playgroud)

不幸的是,这是我的理解.我不知道如何利用这种关系来创建喜欢并将它们与相应的书和用户相关联.

我的想法是,如果用户不喜欢这本书,则向用户显示"喜欢"按钮,或者如果他不喜欢,则为用户提供"喜欢"按钮.所以基本上,我想要这么简单:

<%  if user likes? %>

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

<% else %>

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

<% end %>
Run Code Online (Sandbox Code Playgroud)

我使用了#stub,因为我不知道它应该使用什么路由.但无论解决方案是什么,我都希望它重定向到相同的页面,闪存通知说"喜欢"或"不喜欢".我已经为like_button和different_button类提供了div背景图像,这就是我将它们作为上面的图像链接实现的原因.

任何形式的指导或帮助,将深表感谢.谢谢

UPDATE

我在下面跟随Bennick的指导,但我仍然坚持使用rails控制台.我认为,如果我在控制台中遇到错误,那么前进是没有意义的.

正如所建议的,我在控制台中尝试了这个:

正如我已经有用户我没有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).

ben*_*ick 6

好的,这里有很多项目.我要把你带到堆栈(模型 - > 关联 - > 控制器 - > 视图 - > 路由器).通常,在设计Web应用程序时,您需要从数据库层开始,然后逐步完成工作.所以我们会在这里做.

模型

您可以在此处决定所需的数据库对象,并创建数据库表来表示它们.如果您还没有,请阅读Rails 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
Run Code Online (Sandbox Code Playgroud)

请注意,我们需要包含,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控制台会话的示例: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">]
Run Code Online (Sandbox Code Playgroud)

如有疑问,请使用rails控制台.你将从中学到很多东西.

调节器

为了使最终用户与您的数据库对象进行交互,需要一个控制器来促进交换.再次,阅读相关的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
Run Code Online (Sandbox Code Playgroud)

路由器

路由器将外部http请求连接到您的控制器操作.在您的情况下,您只需要:

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

  resources :likes

 end
Run Code Online (Sandbox Code Playgroud)

这是一个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
Run Code Online (Sandbox Code Playgroud)

帮自己一个忙,阅读本指南:http://guides.rubyonrails.org/routing.html 它将解释这些路线是什么以及它们如何工作.Rails遵循REST,就像大多数现代Web开发世界一样.

视图

在您的视图中,您将需要一个表单供用户进行交互.此表单将数据发送到应用程序,特别是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 %>
Run Code Online (Sandbox Code Playgroud)

结论

我希望这会给你一些指导.

在将来尝试并使您的问题更具体,因为这个问题涵盖了一个很大的领域.我刚刚开始积极回馈所以我可能已经完成了它.我在第一次出发时收到了大量的免费指导和帮助.现在是时候我回报了.

花点时间,当您收到错误时,只需将其发布到Google.您最终可能会遇到Stack Overflow问题.

干杯!