Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Okay there are a number of items here. I'm going to walk you up the <em>stack</em> (<em>model</em> -> <em>associations</em> -> <em>controller</em> -> <em>view</em> -> <em>router</em>). Typically when you design a web application you start with the database layer and work your way up. So we will do that here. </p> <p><strong>Model</strong></p> <p>This is where you decide what database objects you need and create database tables to represent them. If you have not already, read the Rails Guide to migrations: <a href="http://guides.rubyonrails.org/migrations.html" rel="nofollow">http://guides.rubyonrails.org/migrations.html</a></p> <p>In your case this setup would be appropriate:</p> <pre><code>class Book &lt; ActiveRecord::Base attr_accessible :title has_many :likes has_many :users, through: :likes end class User &lt; ActiveRecord::Base attr_accessible :name has_many :likes has_many :books, through: :likes end class Like &lt; ActiveRecord::Base attr_accessible :book, :user belongs_to :book belongs_to :user end </code></pre> <p>Notice that we need include <code>attr_accessible</code> so we don't get any mass-assignment errors. Please not that in Rails 4 this security feature has moved into the controller. For more on this see these or search the inter webs: <a href="http://blog.teamtreehouse.com/rails-4-strong-paremeters" rel="nofollow">http://blog.teamtreehouse.com/rails-4-strong-paremeters</a> <a href="http://weblog.rubyonrails.org/2012/3/21/strong-parameters/" rel="nofollow">http://weblog.rubyonrails.org/2012/3/21/strong-parameters/</a></p> <p><strong>Associations</strong></p> <p>You should read the Rails guide on associations: <a href="http://guides.rubyonrails.org/association_basics.html" rel="nofollow">http://guides.rubyonrails.org/association_basics.html</a></p> <p>This will give you a good idea on how database objects (Active Record objects) interact with one another. In your question you have already set these up. Once an association is made Rails provides a number of methods used to access them. Here is an example rails console session: <code>rails c</code></p> <pre><code># Create a user user = User.create(:name =&gt; "Ryan") # I'm assuming User just requires a name for simplicity =&gt; #&lt;User id: 1, name: "Ryan"&gt; # Create two a books book = Book.create(:title =&gt; "Game of Thrones") =&gt; #&lt;Book id: 1, title: "Game of Thrones"&gt; book2 = Book.create(:title =&gt; "The Well-Grounded Rubyist") =&gt; #&lt;Book id: 2, title: "The Well-Grounded Rubyist"&gt; # Create a two likes from the books and the user record like = Like.create(:user =&gt; user, :book =&gt; book) =&gt; #&lt;Like id: 1, user_id: 1, book_id: 1&gt; like2 = Like.create(:user =&gt; user, :book =&gt; book2) =&gt; #&lt;Like id: 2, user_id: 1, book_id: 2&gt; # Notice how the keys glue the associations # Query a user's likes user.likes.count =&gt; 2 user.likes =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Like id: 1, user_id: 1, book_id: 1&gt;, #&lt;Like id: 2, user_id: 1, book_id: 2&gt;] # Query a user's books user.books =&gt; #&lt;ActiveRecord::Associations::CollectionProxy [#&lt;Book id: 1, title: "Game of Thrones"&gt;, #&lt;Book id: 1, title: "The Well-Grounded Rubyist"&gt;] </code></pre> <p>When in doubt play with the rails console. You will learn a ton from it.</p> <p><strong>Controller</strong></p> <p>In order for the end user to interact with your database objects a controller is necessary to facilitate the exchange. Again, read the associated Rails Guide: <a href="http://guides.rubyonrails.org/action_controller_overview.html" rel="nofollow">http://guides.rubyonrails.org/action_controller_overview.html</a> If you have not guessed by now I highly recommend reading most of these. </p> <p>In your cause we are creating like objects so lets make a likes controller:</p> <p><code>rails g controller likes index</code></p> <p>This will create the controller with an index action and view file.</p> <pre><code># app/controllers/likes_controller.rb class LikesController &lt; 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 =&gt; book, :user =&gt; current_user) # redirect back to the Like index page and assign a flash redirect_to likes_path, :notice =&gt; "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 =&gt; "You destroyed a like" end end </code></pre> <p><strong>Router</strong></p> <p>The router is what connects external http requests to your controller actions. In your case all you will need is this:</p> <pre><code># config/routers.rb MyApp::Application.routes.draw do resources :likes end </code></pre> <p>This is a Rails shortcut that sets up 7 standard routes with associated helpers:</p> <pre><code> 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 </code></pre> <p>Do yourself a favor and read this guide: <a href="http://guides.rubyonrails.org/routing.html" rel="nofollow">http://guides.rubyonrails.org/routing.html</a> It will explain what these routes are and how they work. Rails follows REST as does most of the modern web development world.</p> <p><strong>View</strong></p> <p>In your view you will need a form for users to interact with. This form will send data to the application, specifically to your LikesController actions.</p> <pre><code># app/views/likes/index.html.erb # show your flash messages &lt;% flash.each do |name, msg| %&gt; &lt;div class="alert &lt;%= "alert-#{name}" %&gt;"&gt; &lt;%= msg %&gt; &lt;/div&gt; &lt;% end %&gt; &lt;h1&gt;Books you may or may not like&lt;/h1&gt; # For each book &lt;% @books.each do |book| %&gt; &lt;% unless @user.books.include?(book) %&gt; # 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 &lt;%= form_tag likes_path do %&gt; &lt;%= hidden_field_tag 'book_id', book.id %&gt; # Clicking this sends a request: POST /likes with params of: book_id=123 &lt;%= submit_tag "Like this book", :class =&gt; "like_button" %&gt; &lt;% end %&gt; &lt;% else %&gt; # Find the like. I'll admit there is probably a better way to do this but it's getting past my bed time. &lt;% like = book.likes.where(:user_id =&gt; @user.id).first %&gt; # Destroy the like associated with this book and user &lt;div class="unlike_button"&gt; # Clicking this sends a request to: DELETE /likes/123 &lt;%= link_to "destroy like", likes_path(like.id), :method =&gt; :delete %&gt; &lt;/div&gt; &lt;% end %&gt; &lt;% end %&gt; </code></pre> <p><strong>Conclusion</strong></p> <p>I hope this gives you some guidance.</p> <p>In the future try and keep your questions more specific as this question covered a big area. I'm just starting to actively give back so I might have over done it. I received a ton of free guidance and help when first starting out. It's about time I return the favor. </p> <p>Take your time and when you get an error, just post it into Google. You will probably end up with a Stack Overflow question.</p> <p>Cheers!</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload