2

For my rails application the associations are as follows:

  • A user has many bookmarks and belongs to user.
  • A user has many friendships.
  • A user has many reminders.
  • A user has many comments.
  • A bookmark has many comments.
  • A comment belongs to a user and belongs to a bookmark.
  • A friendship belongs to a user.
  • A reminder belongs to a user

My routes.rb file:

Rails.application.routes.draw do

  root 'welcome#index'
  get 'home', :to => 'home#index'
  get 'searchApis', :to => 'home#searchApis'

  devise_for :users, :controllers => { registrations: 'registrations' }

  resources :users, shallow: true do
    resources :bookmarks, except: :new
    resources :friendships, only: [:index, :show, :destroy]
    resources :reminders
  end

  resources :bookmarks, shallow: true do
    resources :comments
  end

end

Am I writing these routes out correctly?

When I rake routes, I'm getting bookmarks#index twice so I am confused. The prefix for one of them is bookmark, and the other is bookmarks. Why is this happening?

From my understanding, the application does not need to see all of the bookmarks in an index because they are only visible to the user who made them. However, I want reminders to be visible to the user's friends.

I'm hoping to get suggestions to clean up my routes, if possible. I really doubt I am doing this correctly.

Kenny Zhang
  • 63
  • 2
  • 11
  • Also, I feel like user_bookmarks_path and bookmarks_path is redundant and I do not know how to fix it. – Kenny Zhang Jan 18 '16 at 01:44
  • Just think about how you want the bookmarks index to show -- do you want it to be scoped around a *user's* bookmarks, or site-wide bookmarks? – Richard Peck Jan 18 '16 at 10:27

2 Answers2

1

Shallow provides the :index, :new and :create only. So you're getting index twice. Once from within users and the other bookmarks - comments.

On re-reading your associations at the start of your post, and that comments belongs_to both users AND bookmarks, it's probably a good idea to create a Polymorphic relationship.

A rough guide would be for your models,

class Comment < ActiveRecord::Base
  belongs_to :messages, polymorphic: true
end

class User < ActiveRecord::Base
  has_many :comments, as: :messages
end

class Bookmark < ActiveRecord::Base
  has_many :comments, as: :messages

Then either rails generate migration Comments if you haven't already, and have it look like the following:

class CreateComments < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.string :name
      t.references :messages, polymorphic: true, index: true
      t.timestamps null: false
    end
  end
end

otherwise run a migration to add columns to your Comment model. I.e rails g migration AddMessagesToComments messages:references But be sure to open your new migration file named as above and add polymorphic: true before you rake db:migrate

RuNpiXelruN
  • 1,850
  • 2
  • 17
  • 23
1

My interpretation of your spec:

#config/routes.rb
resources :users, only: [] do #-> show a user's collections (no edit)
   resources :bookmarks, shallow: true, except: [:new, :edit, :update]                 #-> url.com/bookmarks/:id
   resources :comments, :friendships, :reminders, shallow: true, only: [:index, :show] #-> url.com/comments/:id
end

resource :bookmarks, except: :index do #-> url.com/bookmarks/:id
   resources :comments #-> url.com/bookmarks/:bookmark_id/comments/:id -- should be scoped around current_user
end

For the comments controller, do this:

#app/controllers/comments_controller.rb
class CommentsController < ApplicationController
   def new
      @bookmark = Bookmark.find params[:bookmark_id]
      @comment  = @bookmark.comments.new
   end

   def create
      @bookmark     = Bookmark.find params[:bookmark_id]
      @comment      = @bookmark.comments.new bookmark_params
      @comment.user = current_user
      @comment.save
   end
end

Don't make a welcome or home controller, you don't need them.

You can put off-hand actions in your application controller:

#config/routes.rb
root                   'application#index'
get 'home',        to: 'application#home'
get 'search_apis', to: 'application#search_apis'

Of course this is somewhat of an antipattern (you'll end up bloating your ApplicationController), but if you only have obscure "one-off" actions in other controllers, you'll be best suited using the above.


Also, only use snake_case with lowercase for URL's - HTTP's spec determines all URLs should be handled as lowercase:

Converting the scheme and host to lower case. The scheme and host components of the URL are case-insensitive. Most normalizers will convert them to lowercase. Example: → http://www.example.com/

Although that's only for the domain/host, it's applicable in the URL itself, too.

Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • this was very helpful. I am fairly new to this so your refactoring of my application controller logic does clean things up for me a bit. – Kenny Zhang Jan 18 '16 at 19:57