I am using cancan 1.6.8 in my application.
I have to create a Cart in my custom method. So I have added custom actions in my routes.rb. Example:
resources :carts
collection do
get "new_cart"
post "create_cart"
end
end
How to initialize new object(#cart = Cart.new) using load_resource for my custom methods(new_cart, create_cart) ?
Specify :new which actions are new resource actions in addition to :new and :create.
Pass an action name into here if you would like to build a new resource instead of fetch one.
Example:
load_resource :new => [:new_cart, :create_cart]
Reference http://rdoc.info/github/ryanb/cancan/master/CanCan/ControllerAdditions/ClassMethods:load_resource
Related
Route defined as follows
resources :purchases do
collection do
put :wirecardtest
end
end
Controller actions redirect in one of the following manners with associated error generated
format.html { redirect_to wirecardtest_purchase_path(#purchase)
undefined method `wirecardtest_purchase_path'
format.html { redirect_to wirecardtest_purchases_path(#purchase)
/purchases/wirecardtest.44
Behaviour is identical when putting code in view.
The ressource is defined in plural mode, as it ought to be. The redirect, as it is supposed to call a specific ressource should call the singular model-action mode (in plural it would generate the period).
I don't understand how I got into this damned-if-you-do, damned-if-you-don't position.
wirecardtest_purchases PUT /purchases/wirecardtest(.:format) purchases#wirecardtest
That's your mistake right there.. the path is generated as 'wirecardtest_purchases' but you are using 'wirecardtest_purchase' note the missing 's' to pluralize the 'purchase'.
Remember its a collection. So the path method is pluralized by rails.
When in doubt rake routes :)
---Update---
Improving the answer (check comments). Need here is to actually define a route as :member and not a :collection if you want to act upon a single object. Referring to Rails Docs,
resources ::purchases do
member do
get 'wirecardtest'
end
end
I have made a resource.
resources :dashboards
I have a partial file which contains a form and I want to use this partial (as the form elements won't change) to update and create. So here is what I have:
Controller
class DashboardsController < ApplicationController
def new
#dashboard = Dashboard.new
end
end
View
/dashboards/new.html.erb
<%= render :partial => "form", :locals => { :dashboard => #dashboard } %>
Partial Form
/dashboards/_form.html.erb
<%= form_for(#dashboard) do |form| %>
.....
<% end %>
Ruby Guide
The Ruby Guide states:
The Article model is directly available to users of the application, so — following the best practices for developing with Rails — you should declare it a resource. When dealing with RESTful resources, calls to form_for can get significantly easier if you rely on record identification. In short, you can just pass the model instance and have Rails figure out model name and the rest. For example:
## Creating a new article
# long-style:
form_for(#article, :url => articles_path)
# same thing, short-style (record identification gets used):
form_for(#article)
## Editing an existing article
# long-style:
form_for(#article, :url => article_path(#article), :html => { :method => "put" })
# short-style:
form_for(#article)
Result
I thought I have followed the Rails Guide correctly. Because I made #dashboard a resource. I could just pass it into the form and have it handle the action, method and the rest. Instead I'm getting this:
<form accept-charset="UTF-8" action="/dashboards" class="new_dashboard" id="new_dashboard_" method="post">
According to the docs. Shouldn't the action of my form now be "/dashboards/new" because we are on the new action? And should it be passing an extra field declaring the method to be put when I use the same code in the /edit action??
My result is always the same no matter what. The form never changes.
What am I doing wrong?
EDIT
Here is my router info from rake routes
GET /dashboards(.:format) dashboards#index
POST /dashboards(.:format) dashboards#create
GET /dashboards/new(.:format) dashboards#new
GET /dashboards/:id/edit(.:format) dashboards#edit
GET /dashboards/:id(.:format) dashboards#show
PUT /dashboards/:id(.:format) dashboards#update
DELETE /dashboards/:id(.:format) dashboards#destroy
You are correct that you should be able to "pass #dashboard into the form and have it handle the action, method and the rest." The issue here is what new is in the context of RESTful actions.
When you declare a set of resources with resources :dashboards, you are creating a set of routes which map requests to controller actions:
GET /dashboards index
GET /dashboards/new new
POST /dashboards create
GET /dashboards/:id show
GET /dashboards/:id/edit edit
PUT /dashboards/:id update
DELETE /dashboards/:id destroy
You can check this if you run rake routes.
The issue here is that the new action is defined as a GET request to the path /dashboards/new, i.e. this is the route for the form itself. The URL in the action attribute of the actual form is something else: this is where the form will post the data to with a POST request, which on the server (rails) side will map to the create controller action.
When you use the form helper with form_for(dashboard), a form is created with a route corresponding to what dashboard is: if it is a new record (i.e. it does not yet exist in the database), then the form action will be create (and point to /dashboards), whereas if it already exists it will point to the actual URL for the record (e.g. /dashboards/123). This is what makes the form helpers so useful.
So, to sum up, /dashboards is the correct URL, not for the new action but for the create action, which the form helper uses because dashboard is a new record. new is the route to the page where the form resides, i.e. /dashboards/new.
Hope that makes sense.
p.s. as a side note, you shouldn't be accessing #dashboard in the partial if you are passing it in as a local (:locals => { :dashboard => #dashboard }). Just use dashboard.
I want to add a custom action named "campaign" acting in a similar fashion like REST's "new" in the same controller, but it's purpose is different, so I wanted to separate them. Because, this campaign form will have some additional fields. One other alternative would be a passing an extra parameter to "new" action and render different templates for regular "new" action and custom "campaign". But, I wanna figure out why it didn't work out.
So, I come up with the following route ("messages" is the controller having both "new" and "campaign" actions):
get 'users/:user_id/messages/campaign', as: :campaign_user_message
or
resources :users do
resources: messages do
member do
get 'campaign'
end
end
end
At the console output, I'm getting ActiverRecord:RecordNotFound since it does this:
Started GET "/users/1/messages/campaign" for 127.0.0.1 at 2012-12-22 00:14:38 -0800
Processing by MessagesController#show as HTML
Parameters: {"user_id"=>"1", "id"=>"campaign"}
I'm calling the action in this way:
link_to campaign_user_message_path(#user)
if you want to have route such as "/users/1/messages/campaign" you should write smth like that:
resources :users do
resources :messages do
collection do
get 'campaign'
end
end
end
If you write in your way(with member do ... end) you code will generate url "/users/:user_id/messages/:id/campaign". and you should pass #user and #message:
link_to campaign_user_message_path(#user, #message)
I've did something like this overcome to the mentioned issue:
resources :users do
get 'messages/new_campaign' => 'messages#new_campaign'
post 'messages/create_campaign' => 'messages#create_campaign'
end
So, I can use the url helper "user_messages_new_campaign" to GET the action /users/:user_id/messages/new_campaign"
I'm new to Rails and currently using Rails 3, so please bear with me. I have a basic app, with a basic scaffolded controller/model e.g Contacts.
Amongst the methods for Show/Edit etc.. i have added a method called newcontacts (i have also added a newcontacts.html.erb), which will eventually show the last 5 contacts imported , but at the moment i am using the same code one would find in the basic Index method of a controller (i intend to filter the data at a later point), the method in the controller is -
def newcontacts
#contacts = Contact.all
respond_to do |format|
format.html # index.html.erb
end
end
I can access localhost:3000/contacts which displays the index method action from the contact controller, but when i try and access this method (newcontacts) using localhost:3000/contacts/newcontacts it returns the error
Couldn't find Contact with id=newcontacts
I have looked at the routes.rb file as i believe this is what needs editing, and have added the following line to routes.rb
match 'newcontacts', :to => 'contacts#newcontacts'
but this only works when i call localhost:3000/newcontacts.
So my question is, how do i get the url localhost:3000/contacts/newcontacts to work?
Any help would be great.
I think what you're trying to do is add another RESTful action.
resources :contacts do
# This will map to /contacts/newcontacts
get 'newcontacts', :on => :collection # Or (not and; use only one of these)...
# This will map to /contacts/:id/newcontacts
get 'newcontacts', :on => :member # ... if you want to pass in a contact id.
end
Try this in your routes.rb file:
resources :contacts do
member do
put 'newcontacts'
end
end
That will add in a new action for the contacts controller.
I'm using devise & devise_invitable in a rails 3 project, and I'm trying to manipulate some of the 'User' object fields in the devise controller.
The action is question is this:
def update
self.resource = resource_class.accept_invitation!(params[resource_name])
resource.first_name = 'Lemmechangethis'
if resource.errors.empty?
set_flash_message :notice, :updated
sign_in(resource_name, resource)
respond_with resource, :location => after_accept_path_for(resource)
else
respond_with_navigational(resource){ render_with_scope :edit }
end
end
I'd have thought that the (commented out) resource.first_name call would influence resource in much the same way as a model - but it doesn't seem to. I'm still getting a 'blank' validation error on this form.
So, the question is, how do I specify values to the User model in devise (and/or devise_invitable) that will actually be subject to verification?
Any suggestions appreciated,
John
resource does return a User models instance. So the resource.first_name = 'Lemmechangethis' statement does change your User models instance but it doesnot trigger your User models validations, which is probably why resource.errors always returns an empty array. One way to trigger the User models validation is to call resource.valid? for example. You can then check the resource.errors array for specific error messages.