Totally change url for action - ruby-on-rails-3.1

I have the following in my routes:
resource :login, only: [:new, :create, :destroy]
resources :users, only: [:new, :create] do
resources :notes
end
but I would like to have url 'my-domain/login' instead of 'my-domain/login/new' and 'my-domain/register' instead of 'my-domain/users/new'.
How can I do than? I have tried the following but it didn't work:
match 'login' => 'login#new'
match 'register' => 'users#new'
resource :login, only: [:create, :destroy]
resources :users, only: [:create] do
resources :notes
end
This gives me error
undefined local variable or method `logins_path' for #<#<Class:0x007fd99c40c608>:0x007fd99c87bdd8>
while visiting 'my-domain/login'

Try this:
match '/login', to: 'login#new'
match '/register', to: 'users#new'
resource :login, only: [:new, :create, :destroy]
A very good tutorial (dare I say "The Best") for learning Ruby on Rails is railstutorial.org. There is a chapter about making a working login and register page.
UPDATE
If you don't want users to visit /users/new I think your current users resources works:
resources :users, only: [:create] do
resources :note
end
Since it only matches a route for users/create. You can also redirect users to /register if they go to /users/new. The new action in your Users Controller:
def new
redirect_to register_path
end

Related

No Route Matches DELETE Sessions Api

I've started to create an Api for my rails application. I am currently creating the Sessions Controller for Log in.
But for some reason I am getting this error
Started DELETE "/api/v1/sessions/?auth_token=6157d3673725013ebddbb5e26e8cd64756949110"
for 127.0.0.1 at 2014-08-29 18:54:18 -0700
ActionController::RoutingError (No route matches [DELETE] "/api/v1/sessions"):
I am not understanding why this is happening. Sign Out seems to work perfectly on the actual web application.
I know it may need an ID according to the rake routes but I'm not sure how to implement this.
API CONTROLLER
module Api
module V1
class SessionsController < ApplicationController
skip_before_filter :verify_authenticity_token,
:if => Proc.new { |c| c.request.format == 'application/json' }
respond_to :json
def destroy
sign_out
render :status => 200,
:json => { :success => true,
:info => "Logged Out",
:data => {} }
end
end
end
end
CONTROLLER
class SessionsController < ApplicationController
def destroy
sign_out
redirect_to root_path
end
end
SESSION HELPER
def sign_out
current_user = nil
cookies.delete(:remember_token)
end
ROUTES
### API Routes
namespace :api, defaults: {format: 'json'} do
scope module: :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resources :sessions, only: [:new, :create, :destroy]
end
end
RAKE ROUTES
api_v1_sessions POST /api/v1/sessions(.:format)
api/v1/sessions#create {:format=>"json"}
api_v1_session DELETE /api/v1/sessions/:id(.:format)
api/v1/sessions#destroy {:format=>"json"}
From the documentation
You can use resource instead of the resources routes helper. It's used to create routes for a singular resource that you don't access using IDs.
namespace :api, defaults: {format: 'json'} do
namespace :v1, constraints: ApiConstraints.new(version: 1, default: true) do
resource :session, only: [:new, :create, :destroy]
end
end
which will give you
GET /session/new
POST /session
DELETE /session

How to cache index page with pagination?

Suppose this my one of admin model
ActiveAdmin.register Theme do
menu :if => proc{ current_admin_user.super_admin?}
after_filter :only => [:create, :update, :destroy] do
expire_action :action => :show
expire_action :action => :index
end
controller do
caches_action :index, :show
end
end
with this code caching is done, but on index page with pagination i am facing issue, that is i am not able to visit another page of Theme.
How to implement something like this
https://github.com/amatsuda/kaminari#creating-friendly-urls-and-caching
this is what fixed the issue:
caches_action :index, :cache_path => Proc.new { |c| c.params }
This will generate new cache for specific paginate param's
Read More

Update Action with no show view

I have an Item model that I do not need a separate show view for. Instead, when the item is updated I would like to return the user to the index. When the form is submitted to edit an item, you get an error like this : No route matches [PUT] "/items/1"
Here is the routes file
Order::Application.routes.draw do
root to: 'static_pages#home'
resources :static_pages
resources :customers
resources :demands
resources :items, only: [:new, :create, :destroy, :index, :edit]
end
Here is the controller
class ItemsController < ApplicationController
def index
#items = Item.all
end
def new
#item = Item.new
end
def create
#item = Item.new(params[:item])
if #item.save
flash[:success] = "Item saved!"
redirect_to items_path
else
render new_item_path
end
end
def destroy
Item.find(params[:id]).destroy
redirect_to items_path
end
def edit
#item = Item.find(params[:id])
end
def update
#item = Item.find(params[:id])
if #item.update_attributes(params[:item])
redirect_to 'items#index'
flash[:success] = "Item updated!"
else
render 'edit'
end
end
end
Here is the model
class Item < ActiveRecord::Base
attr_accessible :name, :price
validates :name, presence: true
VALID_PRICE_REGEX = /^[+-]?[0-9]{1,3}(?:,?[0-9]{3})*\.[0-9]{2}$/
validates :price, presence: true, format: {with: VALID_PRICE_REGEX}
end
You're missing the update action for items in your routes file.
resources :items, only: [:new, :create, :destroy, :index, :edit]
should be
resources :items, only: [:new, :create, :destroy, :index, :edit, :update]
or, more concisely,
resources :items, except: [:show]

Devise & CanCan — Issues with CanCan 2.0 API

I'd like to have additional attributes for my User model and don't want to create a separate Profile model.
I'm trying to update custom fields with standart «update» from RESTful set of actions:
class UsersController < ApplicationController
before_filter :authenticate_user!
# ...
def update
#user = User.find(params[:id])
authorize! :update, #user
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
And it all goes fine except the fact that the current_user is able to update any user's profile. It seems I can't restrict any User action. I've tried:
can :update, User, :id => user.id
and
cannot :update, User # at all
with no luck. Using Devise 1.5.0 and CanCan 2.0.0.alpha
Here's my ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new(:role => nil) # guest user (not logged in)
can :access, :all
if user.admin?
can :manage, :all
else
can :read, Review
if user.customer?
can :update, User, :id => user.id
can [:create, :update, :destroy], Review, :user_id => user.id
end
end
end
end
Code looks good to me.
What if you try to simplify the second condition first and take out the customer condition? And maybe take out "can :access, :all
Something like:
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new(:role => nil) # guest user (not logged in)
if user.admin?
can :access, :all
else
can :read, :all
can :update, :users, :id => user.id
can [:create, :update, :destroy], :reviews, :user_id => user.id
end
end
end
Does your restriction work for Reviews (that user can only edit his own reviews) ?
I have a similar ability file but I always work with a seperate profile model..

Fail at redirect expectation in a controller spec

I am using Devise 1.4.2, RSpec 2.6.0 and Rails 3.1.0.rc6. My routes.rb looks like this:
scope "(:locale)", :locale => /e(s|n)/ do
resources :demotivideos, :only => [:index, :show]
devise_for :users
namespace "admin" do
resources :demotivideos, :except => [:index, :show]
end
end
I am spec'ing that, when a not logged in user acces new, create or update, he should be redirected to new_user_session_path. For this, I am using the following code
context "when not logged in" do
before(:each) do
sign_out user
end
describe "GET new" do
it "should redirect to new user session" do
get :new
response.should redirect_to(new_user_session_path)
end
end
describe "POST create" do
it "should redirect to new user session" do
post :create, :demotivideo => valid_attributes
response.should redirect_to(new_user_session_path)
end
end
describe "PUT update" do
it "should redirect to new user session" do
put :update, :id => 1, :demotivideo => valid_attributes
response.should redirect_to(new_user_session_path)
end
end
end
All are failing because of the same reason: expected route includes the locale (by default en) but the actual redirect was to the same path without locale. My application controller was modified as told in Rails Guides:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :set_locale
def default_url_options(options={})
logger.debug "default_url_options is passed options: #{options.inspect}\n"
{ :locale => I18n.locale }
end
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end
What am I doing wrong?
Seems like though Rails Guides uses def default_url_options in Devise you need def self.default_url_options. Don't know the difference, though.

Resources