I have a rails app where Users can create Programs and other things yet to come, we'll say Plans (hypothetically).
Users can also like Programs and Plans. (Like is polymorphic)
I am trying to figure out routes so I can see the Programs a User creates, all the things a User likes, or just Programs or just Plans a User likes.
I have these routes, but this doesn't seem to be right.
resources :users, :only => [:index,:show] do
resources :programs, :only => [:index]
resources :likes, :only => [:index] do
resources :programs, :only => [:index]
end
end
The route for programs that a user likes requires a URL like: users/user_id/likes/like_id/program.
How do I create a URL like: users/user_id/likes/programs and get all programs that are liked.
I am using the Socialization Gem which has a method for "likeables_relation(Class)" which returns a relation of whatever class is requested. I just need help with the routing.
I've just tried with the following routes:
resources :users, :only => [:index,:show] do
resources :programs, :only => [:index]
resources :likes, :only => [:index] do
collection do
get :programs
end
end
end
and the
http://localhost:3000/users/1/likes/programs
works fine.
It required adding a new action 'programs' to the LikesController class.
This is what rake routes returns:
programs_user_likes GET /users/:user_id/likes/programs(.:format) likes#programs
Related
IN the first few lines is where i made the changes. Is there a way I can post the project so i can give the most information possible?
also i am not using the users controller/file at all. Does authorization require me to use the USer scaffold, because i am using the Newuser scaffold.
Cms::Application.routes.draw do
root :to => "home#merchant"
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
resources :newusers
resources :users
resources :maintenances
resources :leases
resources :sales
resources :saleterminals
resources :salesreps
resources :terminaltypes
resources :processings
resources :manufacturers
resources :promotions
get "community/index"
resources :currents
resources :merchants
get "home/index"
get "home/about"
get "home/contact"
get "home/processing101"
get "home/terminaloptions"
get "home/weekend"
get "home/conditionsofuse"
get "home/privacypolicy"
get "home/announcements"
get "home/support"
get "home/sitemap"
get "home/search"
post "home/search"
end
Routes
A piece of advice - you can DRY up your routes by declaring multiple resources sequentially like so:
#config/routes.rb
Cms::Application.routes.draw do
root to: "home#show", id: "merchant"
controller :sessions do
get 'login' => :new
post 'login' => :create
delete 'logout' => :destroy
end
resources :newusers, :users, :maintenances, :leases, :sales, :saleterminals, :salesreps, :terminaltypes, :processings, :manufacturers, :promotions, :currents, :merchants
resources :community, only: :index
resources :home, only: [:index, :show] do
collection do
post :search
end
end
end
Something to note is I moved your entire home actions to send to the show action. Reason being if you want to show individual pages, you'll just need a show action like so:
#app/controllers/home_controller.rb
Class HomeController < ActiveRecord::Base
def show
render "home##{params[:id]}"
end
end
Authentication vs Authorization
Authentication is whether someone is a user or not
Authorization is whether that user has permission to do
certain things or not
If you're looking to authenticate the user, you may be better suited to using a gem called Devise, which handles the entire authentication process, from signup to sessions. There is a Railscast about this here
--
Fix
In reference to your issue, if you want to show projects information, why don't you just have a projects controller with the only actions as index and show:
#config/routes.rb
resources :projects, only: [:index, :show]
If you want to then allow users to upload or change projects, you can use an "admin" area of sorts, like this:
#config/routes.rb
namespace :admin do
resources :projects, except: :index #-> /admin/projects/new
end
I have the following resource block
resources :projects, :except => [:destroy] do
resources :tasks, :except => [:index]
get "tasks/:id/change_state" => "tasks#change_state", :as => "task_change_state"
get "tasks/:id/assign_user" => "tasks#assign_user", :as => "task_assign_user"
get "tasks/:id/unassign" => "tasks#unassign", :as => "task_unassign"
end
I'm wondering how I can refactor those routes a bit without touching the path. I tried doing the following:
resources :projects, :except => [:destroy] do
resources :tasks, :except => [:index] do
member do
get 'change_state'
get 'assign_user'
get 'task_unassign'
end
end
end
But that leaves the route method names with tasks as plural. I need the URL to be plural, much like in the original get method call. But I need the method name to be singular, as I would prefer to not change the implementation across the app.
I am using Rails 3.2
I want to have routing pretty much exactly like github, so:
root/(username)
root/(username)/(projectname)
root/(username)/(projectname)/issus
etc.
I am trying something like this:
resources :publishers do
resources :magazines do
resources :photos
end
end
But that gives routes like this:
/publishers/1/magazines/2/photos/3
A project I am looking at does the following which seems to work but does not seem to be for me.
resources :projects, :constraints => { :id => /[^\/]+/ }, :except => [:new, :create, :index], :path => "/" do
member do
get "team"
get "wall"
get "graph"
get "files"
end
resources :wikis, :only => [:show, :edit, :destroy, :create] do
member do
get "history"
end
end
If you want to get rid of the id number (which is rails default) and use a name I suggest the FriendlyId gem.
watch this railscast http://railscasts.com/episodes/314-pretty-urls-with-friendlyid
and here is the github page https://github.com/norman/friendly_id
EDIT
This is the article I was looking for, I forgot I bookmarked it months ago.
http://jasoncodes.com/posts/rails-3-nested-resource-slugs
You must to use friendly_id and scope
scope '/:username/:projectname', module: 'users/projects', as: 'users_project' do
resources :issus
resources :photos
end
Users can view and edit account information in my app using UsersController
This controller only ever shows information about the current user.
I want to adjust the routes so that:
get /account accesses UsersController#show, user_id is retrieved from a current_user variable
get /account/edit similarly accesses UsersController#edit
put /account/ will hit UsersController#update, again using current_user instead of an ID
Basically I want to refer to UsersController as 'account' in my URLs and I don't want to use IDs because I'm always just using the current user. I also don't want URLs like /users/1 to function at all.
How can I achieve this?
I think that you are talking about singular resources.
http://guides.rubyonrails.org/routing.html#singular-resources
# Not sure if you need this
resource :users, :only => [:index, :create, :destroy]
# This is what you are looking for
resource :user, :as => :account, :only => [:show, :edit, :update]
Update
Since you need "/account" instead of "/user", you should do
resource :account, :controller => :users, :only => [:show, :edit, :update]
Given your setup, you probably have something like this in your routes.rb:
resources :users
You should be able to just change it to this:
resources :users, :as => "account"
I haven't tested it but this should work. For more info, check the Rails guides on Routing.
Two ways to do it:
In your route.rb:
resources :users, :as=>'accounts'
In your route.rb, remove resources :users and add:
match '/account'=>'users#show'
match '/account/edit'=>'users#edit'
match '/account/'=>'users#update'
I have a projects controller/model. Instead of listing projects on the #index page, I show a list of drop downs, which submits to projects#select, which finds the right Project (I've made sure there can only be 1 for each combination of options) and forwards the user to the #show page for that Project.
So for my routes I do this...
resources :projects, :only => [:index, :show] do
collection do
get 'select'
end
end
And thats fine, but the helper method for #select is 'select_projects', which is understandable but in my case I really want 'select_project'. And I really don't want to alias this in another file. No problem I can use :as...
resources :projects, :only => [:index, :show] do
collection do
get 'select', :as => 'select_project'
end
end
But now my helper is 'select_project_projects'. So I cheat a little (still better than aliasing in another file)...
resources :projects, :only => [:index, :show]
match '/projects/select', :to => 'projects#select', :as => 'select_project'
This looks like it might work, but it doesn't because /project/select actually matches the route for 'project#show'. Changing the order of the lines does the trick.
match '/projects/select', :to => 'projects#select', :as => 'select_project'
resources :projects, :only => [:index, :show]
But is there a more elegant way of handling this? I realize this is borderline OCD, but I'd like to be able to have complete control over the route name within the resources block.
use resource instead of resources
you probably don't want to make it a collection route but a member route:
resources :projects, :only => [:index, :show] do
member do
get 'select'
end
end
This way you'll have the select_project helper.
For those that want to rename the helper method side of things (as the title suggests):
resources :posts, as: "articles"