I'm trying to implement basic social network features to allow users to add, delete friends, accept and decline friedship requests.
my user resource looks like this:
resources :users
resources :friends, :controller => :relations
end
which generates this route user_friend DELETE /users/:user_id/friends/:id
But the problem is when I access /users/1, the generated link to the delete_user_friend_path looks like this: http://localhost:3000/users/5/friends/1
You need to pass the user into the helper:
delete_user_friend_path(#user, #friend)
It seems that you were doing:
delete_user_friend_path(#friend)
Which will fill in the :user_id parameter, and assume you want the same :id parameter as the page you are currently on.
Related
Pretty much as the title suggest. I have two models, routes like this:
resources :users do
resources :books
end
- which gives me exactly the kind of urls I'm looking for. The problem is that I need to have a logic where a not logged in user can go in and click "create book", and in the new-page chose to click "new user" or "I have an account", which via javascript loads a form for a new user with all its params, or loads a form with only email and password. How do I create this route to work? With these routes it seems I get the path /users/:user_id/books/new, but then I need the user's ID, which I don't have.
Any Ideas?
By the way. User has_many :books, Book belongs_to :user.
Just add the route without the user id:
# with user_id
resources :users do
resources :books
end
# without user_id
resources :books
It looks dangerous btw to have a user id in the URL. That means that anyone can access the the books of any user, just by changing the URL. The ID of the current user should not appear in your routes at all, but should always use cookies or sessions.
I have client standard resource with CRUD, but I would like to make extension with action select, so that I can have select_clients_path(client).
In clients_controller I have created action select, but I dont know how to create correct routing rule
for now I have created:
resources :clients do
get 'select'
end
but this generates /clients/select.2 but i would like somthing like /clients/select/2 or /clients/select?id=2
thank you
Dorijan
resources :clients do
collection do
get :select
end
end
will create a 'clients/select' route, to which you can pass parameters like '?client_ids=2...' and work with several client records.
alternatively,
resources :clients do
member do
get :select
end
end
will create a 'clients/:id/select' route to work with a single client record
Take a look at http://guides.rubyonrails.org/routing.html#adding-more-restful-actions for more about this functionality, but those blocks will get you pretty far.
I currently have some routes that look like the following:
resources :contests do
member do
get :enter
end
end
This allows me to do an HTTP GET on a URL that looks like /contests/5/enter. Now, a user can go in, fill in some forms, and be able to submit an entry to the contest. So I'd also like to be able to POST to this URL. I tried doing the following:
resources :contests do
member do
get :enter
post :enter
end
end
This posts to the same controller#action as the GET member that I have specified, so it's not really intuitive. I'd like to be able to direct it to a separate action if at all possible. What's the best way of doing that? I am using Ruby on Rails 4 beta currently.
** UPDATE **
I tried the following but I get an ArgumentError exception when I start the server:
resources :contests do
member do
get :enter
post :enter => "contests#create_entry"
end
end
You can do something like this:
resources :contests do
member do
get :enter
post '/enter', to: "contests#create_entry", as: "create_entry"
end
end
However i agree with Ola Tuvesson, you should definitely create a new controller and routes for entries, even though you may not have a model, similiar to how you often have a session controller for login and logout. Something like this:
resources :contests do
resources :entries, only: [:new, :create]
end
You can specify the controller/action you want to point a route at.
get :enter => "controller#get_enter"
post :enter => "controller#post_enter"
I would suggest you make the entries for a contest a child model of contests. That would give you all the CRUD methods on entries and your routes would simply be:
resources :contests do
resources :entries
end
A GET of /contests/5/entries/new will give you the form for adding an entry and when this POSTs to /contests/5/entries it would create a new entry. It also makes it easy to list all entries for a competition etc. You can easily create the controller, model and the associated views with the scaffold generator, for example:
rails g scaffold Entry contest:references name:string email:string
The references column type tells the generator to link Contests to Entries in a one to many relationship. Job done.
Edit:
If you still want to rename your routes, here's how:
http://guides.rubyonrails.org/routing.html#overriding-the-named-helpers
HTH
The Application Concept:
I'm building a Ruby on Rails [3.2] application at the moment, which consists of 2 very basic controllers - accounts for the user authentication, and messages which belong to the accounts.
# app/models/account.rb
class Account < ActiveRecord::Base
has_many :messages
end
# app/models/message.rb
class Message < ActiveRecord::Base
belongs_to :accounts
end
I then, of coarse, setup my routes.rb to allow users to view their messages nested under accounts:
# config/routes.rb
resources :accounts do
resources :messages
end
The Question:
I want users to access their accounts without using an ID parameter in the URL like this: example.com/accounts/, which works perfectly fine.
Whenever I try and go to: example.com/accounts/messages however, rails treats "messages" as a parameter for the accounts_controller! The only way I can access messages now is by going: /accounts/5236/messages - which is NOT what I want.
My question is, is there a way to block/mask rails from checking parameters on my accounts controller so that I can access my messages like the example above? I'm really puzzled on this one, so please share your thoughts and ideas!
Your defined routes
resources :accounts do
resources :messages
end
implies you can only have URL like this :
/accounts/
/accounts/:id
/accounts/:id/:action
/accounts/:id/messages/
/accounts/:id/messages/:id
/accounts/:id/messages/:id/:action
If you want specify the URL /accounts/messages/, you must specify it in the routes
resources :accounts, :collection => { :messages => :get } do
resource :messages
end
Just to add some closure to this question, I've decided to go with this solution in my routes.rb file:
get "/accounts/messages" => "messages#index", :as => :message
This works well, but the only downside is that it has to be manually added each time if you add controlers under the accounts namespace down the track. Oh well.
ForgetTheNorm also has a fantastic alternate solution below, so give that a shot if this doesn't work for you!
In my 'routes.rb' file I have this code:
resources :users
that maps my user's controller like this.
If I want to map the "reset" view/url for users (Path: /users/reset) what code I have to insert in the 'routes.rb' file?
Two options - I'm assuming you're just going to act on the session user so you don't need to pass in an id to operate on? If so, you'll need to make a few additional changes...
Use an explicit route:
match "/users/reset" => 'users#reset', :as => 'reset_user'
The 'as' part is optional.
Add a new route that operations on a 'collection'. This gets you your route but feels like a hack, I wouldn't recommend it.
resources :users do
collection do
get 'reset'
end
end
Do this:
resources :user do
member do
get 'reset'
end
end
See this section in the Rails Guide you referred to.