Rails - calling a method in controller using link_to - ruby-on-rails

I'm trying to call a method in controller from my index.html file while staying on the same path... is it possible... can anyone help me
index.html
<%= link_to "Click", controller: "products", action: "click" %>
controller.rb
def click
puts "click called!!!"
end
routes
get 'click'
Error: Missing :controller key on routes definition

Per the documentation of Rails Routes, you got to specify the controller and the action where it is routed, in your case the Products controller within the click action.
So in your routes.rb file your proper get syntax should include the destination, like this:
get '/products/:id', to: 'products#click'
Also in your link_to you should include the ID of the product so the routing passes the id to the controller and you should include logic in your controller to manipulate that ID how you need. See this.
PS: Don't name your action click , name it as the actual action to perform on a product, like show. Please also check what Resources routing is.

Related

Custom action_item on show page only

I'm struggling to create an action_item for a show page (not the index) of a resource. I need to add a button on the show page, which when the user clicks it, updates a single attribute on the resource (in this case 'status' of a SupportSession). I have created a method on my SupportSession model called approval_confirmed which accepts a parameter called support_session_id - I'd like this method to be called.
(BTW I'm not sure which HTTP verb to use (patch, put, get) though I've settled on patch).
Here's how my resource is set-up:
ActiveAdmin.register SupportSession, as: "SUSupportSession" do
(I've given this resource a custom name/alias because different users use this resource in different ways; so for simplicity I keep them in separate files.)
Here is my action_item code:
action_item only: [:show] do
link_to 'Approve session', approve_su_support_session_path, method: :patch
end
Here is the corresponding member_action (which I understand is called by the action_item?):
member_action :approve, method: :patch do
SupportSession.with(support_session_id: resource.id).approval_confirmed
redirect_to su_support_session_path, notice: "Your support session has been approved!"
end
This creates a new route (output of rails routes below):
approve_su_support_session PATCH /su_support_sessions/:id/approve(.:format) su_support_sessions#approve
However, when I try to open the index page (to select a record from the table and move to its show page) I get this error:
ActionController::UrlGenerationError in SuSupportSessions#index
No route matches {:action=>"approve", :controller=>"su_support_sessions"}, missing required keys: [:id]
I understand this is something to do with the fact that there is no id parameter on the index page (although I don't understand why it's getting called on the index page because I only need this button on the show page - where the id will appear once a user clicks 'view' on any item listed in a table).
Thanks for your help. I think I'm getting terribly mixed up with how ActiveAdmin controllers connect to the underlying model.
As #max says in comment above your have to pass an argument to your path, resource or resource.id works.
Regarding your current error I guess it could be caused because you have not mentionned the action you want to do.
action_item :approve, only: [:show] do
link_to 'Approve session', approve_su_support_session_path(resource), method: :patch
end
I hope it helps. Let me know.

What action after "submit"?

In rails after pressing submit button in "new" I automatically come to "create" (similar after "edit" to "update"). All my params getting in "new" available in "create". This is by default.
If I have "export" instead of "new" and "process_export" instead of "create" - how reach similar effect?
If I get you right than you don't want to send the form to the default create action but rather to another, in your example to a process_export action.
All you have to do is to create a route in your routes.rb and set a custom form action url.
Example:
routes.rb
get '/process_export' => 'your_controller#export' # replace `your_controller` with your controller name
post '/process_export' => 'your_controller#process_export', as: :process_export
In your export view:
<%= form_for :resource, url: process_export_path do |f| %> <!-- Replace resource with your proper resource -->
<!-- Your form here -->
<% end %>
But I highly recommend you to observe the conventions of REST. It makes your live a lot easier.
Here are two resources which explain it in more detail:
Rails Routing: http://guides.rubyonrails.org/routing.html
Form Helpers: http://guides.rubyonrails.org/form_helpers.html
Rails follow the Convention over Configuration concept . The 7 methods of REST are automatically called from the controller when a similar request comes in the Rails 4 . For ex : the GET request will call new method , POST will call create method , DELETE will call destroy method etc .
Now , if you are creating a custom method in your controller like export and if you want to call it after the clicking on the submit button , you have to set routes accordingly in the routes.rb file . Which can be done as :
post "/chats" => "chats#export"
Here , chats is the controller and export is the method in that controller which you want to call on the submit action.
You can do :
$ > rails g scaffold Controller_name
and this will generate all the 7 REST methods in your controller automatically and similar routes are generated which you can check by doing :
$ > rake routes
I hope this helps.

Calling a specific action in a form tag

I have an action vote_for in my question controller.
what is the helper that enbales me to call this action from a view?
i tried :
vote_for_question_path(#question)
but this didn't work. ?
Since you've already defined resourceful routes for the Question resource, you should start by adding a member route on your existing resource route:
# config/routes.rb
resources :questions do
member do
get 'vote_for'
end
end
This will create the following route:
vote_for_question GET /questions/:id/vote_for(.:format) questions#vote_for
Next, create a controller action for the resulting route:
# app/controllers/questions_controller.rb
def vote_for
# logic goes here
end
Finally, in your view, you can construct a link to the route by passing the collection path to the link_to helper:
<%= link_to "Vote", vote_for_question_path(#question) %>
UPDATE:
If you'd rather represent the link as an HTML button than an <a> tag (as the OP is proposing in the comments to this answer), you can use the button_to form helper as follows:
<%= button_to "Vote", vote_for_question_path(#question), method: "get" %>
Note that, because you're replacing the link with a button, you should ensure that you're passing the correct HTTP submission method (which is GET in this instance) as an argument.
The path helpers only come when you define them in your routes.rb as a named route. So if you want a named non-RESTful route (which you do), you should add to your routes file:
get 'vote_for_question/:id', to: 'question#vote_for', as: 'vote_for_question'
And then you can call vote_for_question_path(#question.id) in your views and it will generate e.g. /vote_for_question/1.
See http://guides.rubyonrails.org/routing.html#generating-paths-and-urls-from-code for more on this.

How do I create a rails controller action?

My rails app has a single CustomerSelectionController, with two actions:
index: which shows a form where the user can enter customer information and
select: which just displays a static page.
class CustomerSelectionController < ApplicationController
def index
end
def select
end
end
I've created an entry in my routes.rb file:
resources :customer_selection
and the form in the index view looks like:
<h1>Customer Selection</h1>
<%= form_tag("customer_selection/select", :method => "get") do %>
<%= submit_tag("Select") %>
<% end %>
however when I click on the Select button in the browser, all I get is:
Unknown action
The action 'show' could not be found for CustomerSelectionController
I'm not sure why it is trying to perform an action called show? I haven't defined or referenced one anywhere.
I'm not sure why it is trying to perform an action called show? I haven't defined or referenced one anywhere.
Yes you have. That's what resources does. It defines the seven default RESTful routes: index, show, new, create, edit, update and destroy. When you route to /customer_selection/select, the route that matches is "/customer_action/:id", or the "show" route. Rails instantiates your controller and attempts to invoke the "show" action on it, passing in an ID of "select".
If you want to add a route in addition to those, you need to explicitly define it, and you should also explicitly state which routes you want if you don't want all seven:
resources :customer_selection, only: %w(index) do
collection { get :select }
# or
# get :select, on: :collection
end
Since you have so few routes, you can also just define them without using resources:
get "/customer_selection" => "customer_selection#index"
get "/customer_select/select"
Note that, in the second route, the "customer_select#select" is implied. In a route with only two segments, Rails will default to "/:controller/:action" if you don't specify a controller/action.

simple link_to in rails

I have a page app/views/new/news.html.erb and I simply want to link to this page from within my layouts/application.html.erb. Can someone please help! I have been struggling with this all morning.
I have tried things like <%= link_to "News", ... But I'm not really sure where to go from there.
You don't "link" to a view, you link to a controller which renders that view. Then, you'll need an entry in your routes.rb to wire up the url routing for that controller. If you have a controller named NewsController with a method called index and an entry in your routes.rb that looks like resources :news the following link_to should work: link_to "News", news_path.
In case it's not clear, the index method in your NewsController needs to have render :news in it.
Sounds like you may want to check out the guide on this topic: http://guides.rubyonrails.org/routing.html
If you have it setup correctly you should have a plural for your controller (i.e. news instead of new) and the following should work:
<%= link_to 'News', :controller => "news", :action => :news %>
This is assuming you are using scaffold.
If are adding this folder and page manually: for dynamic page, you have to create an action in your controller. For static page, you have to put it in your public folder.
You can always run
rake routes > routes.txt
in your application directory, which will dump a list of all routes into a txt file. Choose path that leads to action and controller you want, and then supply it as a param for link_to method :)

Resources