Rails 3: Remap user_path route with match rule - model-view-controller

I have got this in my routes file:
resources :users
match '/#:id' => 'users#show'
When I go to /#radeks then it would be the same as if I would go to /users/radeks. However, I use user_path in my views, but this points to /users/radeks which I don't want.
How can I make user_path always point to /#:id?
Edit
I also have got this in my User model:
def to_param
name
end

match '/#:id' => 'users#show', :as => 'user'
The :as argument makes this a "named route". See http://guides.rubyonrails.org/routing.html#naming-routes for more info.
NB that you're overriding the default 'user' named route you get automagically from 'resources :users'

Related

How to fix FriendlyID duplicate content for :id and :slug

FriendlyID is consistently showing duplicate content for both /slug and /1. In other words, the correct page is loading for the friendly slug (/new-york), but it's loading the same content for the old, unfriendly slug (/11).
Here's my current configuration:
#config/routes.rb
resources :groups, path: ''
get 'groups/:id' => redirect("/%{id}")
#app/models/group.rb
class Group < ActiveRecord::Base
extend FriendlyId
friendly_id :name, use: [:slugged, :finders]
end
#app/controllers/groups_controller.rb
def show
#group = Group.friendly.find(params[:id])
end
As a potential workaround, I've found putting this in my controller does redirect the bad slugs (/11) to the good slugs (/new-york), but it feels wrong for many reasons (routing outside routes.rb, likely unintended consequences, complex solution for a common problem = probably not the right one).
if request.path != group_path(#group)
return redirect_to #group, :status => :moved_permanently
end
What is the right way to make FriendlyID either (1) redirect :id calls to :slug or (2) simply 404 them?
Thanks to this fantastic comment on Medium, I now have a fully functional and very elegant solution which solves my initial problem (duplicate pages with /new-york and /11) as well as allowing two root-level slug structures to coexist.
get '/:id', to: 'groups#show', constraints: proc {|req| FriendlyId::Slug.where(sluggable_type: 'Group').pluck(:slug).include?(req.params[:id])}, as: :group
get '/:id', to: 'custom_pages#show', constraints: proc {|req| FriendlyId::Slug.where(sluggable_type: 'CustomPage').pluck(:slug).include?(req.params[:id])}, as: :custom_page

NameError in Devise::Registrations - Rails 4

I have an application that breaks down different users into categories , i run into Devise error when i choose the third category
Relevant code
#routes.rb
devise_scope :user do
get "users/select_user_type" => "devise/registrations#select_user_type"
get "users/create_creative_user", :to => "devise/registrations#create_creative_user", :as => "create_creative_user"
end
resources :users
This is the error i am facing -
uninitialized constant ActionView::CompiledTemplates::CreativeRequest
<%= form_for(CreativeRequest.new,url: {action: "create"},:html=>{:method=>:post,:id=>"create_creative_user"}) do|f| %>
Read around a bit and found sometimes cancan causes error with devise , please guide if it's the same case . Thanks in advance .
If you are using CreativeRequest instance in form_for then CreativeRequest should be a model. Make sure you have a class CreativeRequest in app/models/creative_request.rb.

Figuring out rails routes, getting undefined method for my detail_path

My data of a datatable:
def data
theusers.map do |usermap|
[
h(usersmap.spriden_last_name),
h(usermap.spriden_first_name),
h(usermap.spriden_id),
link_to(usermap.gobtpac_username, detail_path(usermap.spriden_id))
]
end
end
the above code resides in app\datatables\helpdesk_datatable.rb
The above works mostly I know it is getting the data, the error I get is with the detail_path
Error on "undefined method" for detail_path... This means it is not building the router dynamically right, correct?
Or I am passing in the wrong thing I tried to pass in usermap.spriden.id and just banner user, same issue. I am really not sure how routes work apparently. I have a details_controller.rb in controllers that has a show method in it and i have the views/details/show.html.erb which will show the data that was passed into the route, at least I thought. But is it just an ID or an object? so if it just an id i have to look it up again in
the show method right? How do routes like this look? I am using devise and cancan too here is my routes file:
NmsuMyaccount::Application.routes.draw do
authenticated :user do
root :to => 'home#index'
match 'home', :to => 'home#index', :via => :get
end
#get 'show-details' => "details#show", as: 'show_details'
resources :details
devise_for :users
resources :users
# In order for an unauthorized user access this controller#action, this needs to be in a scope, but I don't know why.
devise_scope :user do
match 'home', :to => 'home#index', :via => :get
end
end
Also hitting the end point localhost:3000 is an error, I have to goto /home, although devise does work just fine. So thought I was close but for the life of me cannot get the detail_path to work, and I thought it was a plural issue so tried details, and just detail no path etc. No dice.
I don't believe that you have access to the route helpers that Rails provides inside your custom class. So you have to manually include the module inside your class. Something like:
link_to(usermap.gobtpac_username, Rails.application.routes.url_helpers.detail_path(usermap.spriden_id))
Or:
include Rails.application.routes.url_helpers
# Use it like you are using.
See here for more information about the subject:
Can Rails Routing Helpers (i.e. mymodel_path(model)) be Used in Models?

Devise : /login with param giving `undefined method stringify_keys`

For /login my application is working fine, but for /login?user="something" giving 500
I am using devise gem
routes.rb
devise_for :users, :controllers => { :sessions => 'devise/sessions'}, :skip => [:sessions] do
get '/login' => "devise/sessions#new", :as => :new_user_session
end
error :
Completed 500 Internal Server Error in 263ms
NoMethodError (undefined method `stringify_keys' for "\"something\"":String):
Rendered /usr/local/rvm/gems/ruby-1.9.2-head/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_trace.erb (2.6ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-head/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.7ms)
Rendered /usr/local/rvm/gems/ruby-1.9.2-head/gems/actionpack-3.1.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb within rescues/layout (7.9ms)
stringify_keys is a method that Rails mixes into the Ruby Hash class, so the problem here is that devise is expecting a hash of attribute-value pairs in the user param instead of a plain string. In other words its expecting a User model object rather than just a user name.
The convention that Rails uses for packing nested attribute value pairs into URL query string or HTML form params uses square brackets, so you probably need something like this:
/login?user[name]=someone&user[password]=secret

How to magically supply Active Record scopes with arguments?

I'm not sure this is even possible, but let's see if one of you comes up with a solution. This is more or less about code quality in terms of readability and not an actual problem because I already have a solution. I have a friendship model and a user model. The friendship model is used to model friendships between two users:
class Friendship
def self.requested(user)
where(:user_id => user).where(:status => 'requested')
end
def self.pending(user)
where(:user_id => user).where(:status => 'pending')
end
def self.accepted(user)
where(:user_id => user).where(:status => 'accepted')
end
# ...
end
class User
has_many :friendships
# ...
end
Is it somehow possible to call the requested, pending or accepted scope through
the user model without providing an argument?
a_user.friendships.pending # this does not work, is there a way to get it working?
a_user.friendships.pending(a_user) # works of course!
I think this should work if you take the argument off. Calling pending off of the user object like this should already scope friendships to the appropriate user. Define the method like this:
def self.pending
where(:status => 'pending')
end
And call:
a_user.friendships.pending
Check the logs for the generated query if you're not sure it's working.
If you still want to call it by passing an argument I'd name that method Friendship.pending_for(user).

Resources