undefined method `protect_against_forgery?' for #<#<Class:0x0 - ruby-on-rails

I have the following code in my routes.rb file .
resources :users do
member do
get :following,:followers
end
collection do
put :activate_email
end
end
And I have a user email activation link like this :
<%= link_to "Activate",activate_email_users_url(email_token: #user.email_token),method: :put %>
When I click on the activate link , this is the url that is generated
http://localhost:3000/users/activate_email?email_token=WWNvMN-r_lXgovrQiDlSSQ
Update: Ok, So I think I kno what the problem is . When I look at the html source of the activation email in my gmail which contains the link_to , there is no data-method='put'. So that seems to be the problem . It is always sending a default GET request instead of PUT.
This is my user_mailer/registration_confirmation.html.erb file
<%= javascript_include_tag "application" %>
</head>
Please click on the following link to activate your email
<%= link_to "Activate",activate_email_users_url(email_token: #user.email_token), method: :put %>
This gives the following error :
undefined method `protect_against_forgery?' for #
So , the code <%= javascript_include_tag "application" %> is causing this error. Is there any way around this ?

Sorry, I do not know your purpose, but apparently you have a purpose to activate user.
Try this, if this solution not work, please tell me your action (activate_email) on controller!
see on rake routes output :
activate_email_users PUT /users/activate_email(.:format) users#activate_email
user GET /users/:id(.:format) users#show
when your generate
http://localhost:3000/users/activate_email?email_token=WWNvMN-r_lXgovrQiDlSSQ
Your problem was activate_email considered to be :id
users/activate_email => users/:id
And solution for your problem :
Try removing the method from the link. Its better specifying the method in your routes file. How about replacing match by put in routes as :
resources :users do
member do
get :following,:followers
end
end
put "/users/activate_email/:email_token" => "users#activate_email", :as => "activate"
and on view
<%= link_to "Activate", activate_path(:email_token => #user.email_token) %>
I have not tested this, but I guess this will suffice.
UPDATE
for Question : undefined method `protect_against_forgery?'
Add this to a helper that only your mailer template uses:
def protect_against_forgery?
false
end
NOTE : If You have new question, please create new "Ask Question" and aprrove answer is usefull for this question

If you're trying to activate a single user account you probably don't want to be specifying your route on the collection (which you would use for actions that operate on multiple users).
Here's some (untested) code that should point you in the right direction:
controller :users do
put '/activate/:email_token', :to => :activate, :as => 'activate_email'
end
Which should route a PUT to /activate/xxxx to the UsersController#activate action with a params[:email_token] set as xxxx. It should also give you a #activate_email_url route which you can pass the activation token (you can check what routes your app provides by running rake routes on the command line).

Google redirected me to this question even-though mine was related to rendering a template into a string and not just in the browser. My solution for the template problem was something along these lines:
action_controller = ActionController::Base.new()
action_controller.class_eval do
def protect_against_forgery?
false
end
end
file_string = action_controller.render_to_string('/some_template/template_file',locals: { local_variable: 1 }

Related

Undefined method in controller (Routing)

I'm new at rails and I'm currently working on an already existing application that handles butons like so:
<%= link_to 'Edit', edit_answer_path(ans) %>
That links to the file /answers/edit.html.erb but now I need to make a button that links to the file /answers/comment.html.erb how do I go about doing this?
I already tried with
<%= link_to 'Comment', comment_answer_path(ans) %>
but I get the error "Undefined method 'comment_answer_path'" even after adding this lines to answers_controller :
def comment
ans = Answer.find(params[:id])
end
You need to add a route to your config/routes.rb and then restart the server. Something like
resources :answers do
member do
get 'comment'
end
end
will create the comment_answer_path helper for you as well.
It depends on how you've set up the routes in routes.rb.
You can use rake routes to see the list of all paths and their alias.

ActionController::UrlGenerationError using link_to

I have a controller Posts in which I have a method:
def report_user
...
end
I have a view where I would like a link that will perform some logic (it should NOT actually take the user to a different page, only perform the logic and possibly show a dialog box after completion). The logic is contained in the report_user action in the Posts controller:
<%= link_to "Report User", :controller => :Posts, :action => :report_user %>
I would ultimately like to pass some variables also to the report_user action, however I haven't gotten that far as I've come across this error:
No route matches {:action=>"report_user", :controller=>"Posts"}
message << " missing required keys: #{missing_keys.sort.inspect}" unless missing_keys.empty?
raise ActionController::UrlGenerationError, message
end
I'm not sure what the issue is. There is definitely an action in the Posts controller called report_user and it is not private. I'm not sure what the missing required keys means either. I've seen on SO other people with that error, but they all have routes defined that require parameters. I do not have any routes defined for this. Possibly I"m going about the entire thing in the wrong way?
As Nils suggested, you need an entry in routes.rb. Assuming that this is a member route using a GET request, that entry would look like this.
resources :posts do
get :report_user, on: :member
end
Next, you need to update your link to use the routing helpers that Rails provides.
<%= link_to "Report User", report_user_post_path(#post), remote: true %>
I included the remote: true option b/c you mentioned that clicking the link shouldn't reload the page. The default response for this request will be app/views/posts/report_user.js.erb.
I would encourage you to read up on Rails routing at http://guides.rubyonrails.org/routing.html.

Rails redirecting to a 'show' path when given another path

I have a custom route called "work_path" and when I try to access it I get this error
"Missing template portfolios/show"
I am not trying to access the "show" view, but rather one named "work" (work.html.erb). I have no idea why it keeps trying to get me to the "show view"
My custom route
get 'portfolios/work' => 'portfolios#work', :as => :work
Portolios Controller
def work
#portfolio = #portfolio.active
end
The link I'm using:
<%= link_to "Work", work_path %>
I don't know why it's trying to redirect me.
You probably have also resources :portfolios in routes.rb above your custom route and that causes your problem. Switch these lines' positions.

Why Rails process link_to with :action=>methodname as ID=>methodname

I'm trying to make a link in Rails (2.1) that:
Only appears for admin users
When clicked, executes a method in the controller,
The method executes a small shell script (e.g. a short sql query which outputs a text file),
Prompts the user to download the output text file,
Everything is done on the same page without redirecting to another page (ideally)
I tried these solutions to run a shell script from Ruby: (1), (2). In my reports_controller.rb:
def runreport
#system('sh hello.sh')
puts `whoami` # << this is just to test shell script calling
end
And in my view/report/index.html.erb:
<% if is_logged_in? && logged_in_user.has_role?('Administrator') -%>
<p><span class="encapsulated"><%= link_to "Download File", { :action => 'runreport' } %></span></p>
<% end -%>
(The <span class="encapsulated"> just puts the link in a nice button form). However, when I clicked the link, it returns an error:
ActiveRecord::RecordNotFound in ReportsController#show
Couldn't find Report with ID=runreport
...
app/controllers/reports_controller.rb:100:in `show'
With Parameters:
{"id"=>"runreport"}
It looks like when the link is pointed to itself (reports), the default method to execute is "show". But wasn't it specifically told to do action => 'runreport'? I've scratched my head and looked for answers for a few hours and couldn't figure it out :( Thus, my questions are:
What am I doing wrong?
Why is it looking for the id=>"runreport"?
How to fix the error? and if it's possible to tell it to not do redirection
And what's the ideal way to deliver the file to the user after the script is done?
Thank you in advance for any help/feedback!
Cheers!
EDIT: This is how the routes.rb on reports look like:
map.resources :reports,
:member => { :claim => :put, :close => :put, :open => :put, :baz => :post },
:collection => {:search => :get} do |report|
report.resources :blah, :foo => { :bar => :post }
end
This is on Rails 2.1, so I assume it's different from 3.x
Generally the issue is with the routes.
If you define restful routes as in
map.resources :reports
or in case of rails 3 and above
resources :reports
Its assumed that /reports/:id is the show action. So when you go to "/reports/runreport" it goes to the show action and tries to find an Report object with the Id "runreport".
Read this http://guides.rubyonrails.org/routing.html#resources-on-the-web
You may want to define collection route on reports to make this work. Read this http://guides.rubyonrails.org/routing.html#adding-more-restful-actions
I have not figured out entirely why the controller always defaults to the show method, but I've found a workaround. I just make it call my runreport method when the link is clicked (which will reload the same page), before it calls the show method.
I'm guessing, since the page is always calling the show method, which is a "member" method, it will always look for some id.
Thanks for all your help!

Ruby on Rails: How to print out a string and where does it display at?

I know this is a trivial question. But I have search all over google but cannot find a simple answer to this question.
Basically I have a line that says <%= link_to 'Run it', :method => 'doIt' %> in the view, then in the corresponding controller, I have the doIt method as follows:
def doIt
puts "Just do it"
end
I just want to check that if i click on Run it, it will output the string "Just do it". I ran this on localhost and there is no errors, but I can't find the output "Just do it" anywhere. It is not displayed in the rails console or rails server log. I just want to know where does puts output the string to , where to find it ?
Round 2: So this is what I tried ....
Added this line in the index.html.erb (which is the root)
<%= link_to 'Run it', :method => 'do_it' %>
and in the url, it is just basically http://localhost:3000/ (since i route controller#index as root)
The display is just an underlined 'Run it' that links to 'do_it' method in the controller.
In the controller, i include this method
def do_it
logger.debug "Just do it"
end
when i click on 'Run it', the url change to http://localhost:3000/gollum_starters?method=do_it and in the development.log, the following is written into it:
Started GET "/gollum_starters?method=do_it" for 127.0.0.1 at 2011-08-25 15:27:49 -0700
Processing by GollumStartersController#index as HTML
Parameters: {"method"=>"do_it"}
[1m[35mGollumStarter Load (0.3ms)[0m SELECT "gollum_starters".* FROM "gollum_starters"
Rendered gollum_starters/index.html.erb within layouts/application (3.6ms)
Completed 200 OK in 16ms (Views: 7.7ms | ActiveRecord: 0.3ms)
Additionally, i tried all the logger.error/info/fatal/etc ... and Rails.logger.error/info/fatal/etc, all did not print out the line "Just do it" in the development log
#Paul: I did not touch the environment folder or file, i assume by default when a new rails app is created, it is in development ?
#Maz: Yes you are right, I am just trying to test if the do_it method is getting called. To do that, I just want to print something out in the controller. Can't think of any way simpler that just print a string out, but this problem is making me miserable. I am just using textmate, no IDE.
Round 3:
#Paul thx alot, but i encountered error
My routes files is now:
resources :gollum_starters
root :to => "gollum_starters#index"
match 'gollum_starters/do_it' => 'gollum_starters#do_it', :as => 'do_it'
My index.html.erb is now:
<%= link_to "Do it", do_it_path %>
My gollum_starters_controller.rb
def do_it
logger.debug 'Just do it'
end
I am getting this error:
Couldn't find GollumStarter with ID=do_it
the error is in here, 2nd line:
def show
#gollum_starter = GollumStarter.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #gollum_starter }
end
end
I wonder why does it route to show ? When i click do_it, it actually goes to localhost:3000/gollum_starters/do_it which is correct, but apparently the error points to the show method ?
Round 4:
#Paul, i shifted resources :gollum_starters down:
root :to => "gollum_starters#index"
match 'gollum_starters/do_it' => 'gollum_starters#do_it', :as => 'do_it'
resources :gollum_starters
but got this error (omg i wanna kill myself),
Template is missing
Missing template gollum_starters/do_it with {:handlers=>[:erb, :rjs,
:builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in
view paths "~/project_name/app/views"
:/
---------- Answer to Round 4 ------------
Basically as the error explains, there is no template(i.e a webpage) to show hence error thrown. The solution is to add a redirect_to , in this case I redirect to root_url.
def do_it
logger.debug 'Just do it'
redirect_to(root_url)
end
Everything works now, "Just do it" finally outputs to development.log and the rails server console.
Thank you Maz and Paul and Andrew for helping me out. Learn a lot.
That link_to does not do what you think it does the value for :method is referring to the HTTP verbs.
Taken from the docs for ActionView::Helpers::UrlHelper
:method - Symbol of HTTP verb. Supported verbs are :post, :get, :delete and :put. By default it will be :post.
You would need to define a route in your routes.rb file that uses your method
# The order of routes is important as the first matched will be used
# therefore the match needs to be above 'resources :controller'
match 'controller/do_it' => 'controller#do_it', :as => 'do_it'
resources :gollum_starters # <--- This needs to be below the match or this will catch first
The controller/do_it is the route to be matched
The controller#do_it is the controller followed by the action to be used (separated by #)
The value for :as creates the path do_it_path that can be used in your link_to
Your link_to may look something like
<%= link_to "Do it", do_it_path %>
And to complete the lifecycle of a request you will need to add a view to be rendered
app/views/gollum_startes/do_it.html.erb # <-- Add file
Summary
Doing all of this creates a bit of a mess just to print something out to the logs, but it should help you understand the whole lifecycle a bit better now. Plus this answers serves as a document to help you rewind this mess.
You are not understanding what "method" means in the context of a link.
The "method" here refers to the request method, which means the kind of request you are asking the browser to make. From the perspective of a RESTful application like Rails there are four relevant request types: GET, POST, PUT, and DELETE. These request types affect how the controller responds to a request.
GET => INDEX or SHOW
POST => CREATE
PUT => UPDATE
DELETE => DESTROY
There are two other "standard" rails actions, NEW and EDIT. These are GET requests to present an interface to the user. NEW gives you a form to POST (CREATE) a new object, and EDIT gives you a form to PUT (UPDATE) and existing one.
See the rails guide for more on how HTTP Verbs relate to CRUD operations.
The important, basic thing to understand is that links, by default, are GET requests, and forms, by default, are POST requests.
So, when your link looks like this:
<%= link_to 'Run it', :method => 'do_it' %>
...it is bogus. There is no such HTTP method as "do_it", so you're not triggering anything. Because there is no such method, Rails actually passes this on as a parameter of the URL. Hence if you click that you should see your url bar now says ?method=do_it at the end.
There are several problems with what you're trying to do. First of all, the link_to helper expects at least two arguments: 1, the text for the link, and 2 the HREF for the link. So, you really need to use:
link_to 'Run it', url
Second, you need to know what URL to pass to get your controller action.
Please be familiar with the following rails convention: When referring to a controller action you can abbreviate it using the form: controller_name#controller_action. e.g. pages#show or articles#index.
Assuming your controller is called ExamplesController, you can manually trigger the seven standard controller actions as follows:
link_to 'examples#index', '/examples'
link_to 'examples#show', '/examples/123' # 123 is the id of a specific example
link_to 'examples#new', '/examples/new'
link_to 'examples#create', '/examples', :method => :post
link_to 'examples#edit', '/examples/123/edit'
link_to 'examples#update', '/examples/123', :method => :put
link_to 'examples#destroy', '/examples/123', :method => :delete
Note that in the above, INDEX, SHOW, NEW, and EDIT are all GET requests. You could specify :method => :get but that is unnecessary
To abstract this away and take care of assigning the ID when required Rails provides path helpers.
So, to repeat the above using the path helpers you could use:
link_to 'examples#index', examples_path
link_to 'examples#show', example_path( #example )
link_to 'examples#new', new_example_path
link_to 'examples#create', examples_path, :method => :post
link_to 'examples#edit', edit_example_path( #example )
link_to 'examples#update', example_path( #example ), :method => :put
link_to 'examples#destroy', example_path( #example ), :method => :delete
Now, you get these path helpers from the router, and they are defined in your routes.rb file. Within that file if you define:
resources :examples
...then you will get all the path_helpers above.
If you are using a normal RESTful controller and you want to add a custom action, then you need to make one decision: does the action operate on the entire set of objects handled by that controller (like index) or just a single specific one (like show). The reason this is important is this tells the router whether the new action you're defining needs to receive a record ID as part of the request.
If you want to act on the entire collection of objects, you define:
resources :examples do
collection do
get 'do_it'
end
end
If you want to act on just a single member of the collection you define:
resources :examples do
member do
get 'do_it'
end
end
Where I wrote 'get' in the examples above you can use any of the four verbs -- GET is normally what you do if you want to show a page, and POST is normally what I'd use if you're submitting a form. You can also write this shorthand like so:
resources :examples do
get 'do_it', :on => :collection
post 'something', :on => :member
end
For more on defining custom controller actions, see the rails guide.
Now that you've defined a route, you should run rake routes in terminal to see the name of the new path helper. Let's assume you added do_it as a collection method, your path helper would be: do_it_examples_path.
Now then, back to your link, if you put:
<%= link_to 'Do it.', do_it_examples_path %>
... then you would trigger the do_it action. When the action is triggered your puts should normally render to the server log (assuming you're running rails s in a terminal window you should see it right after started GET on examples#do_it...).
Now, in the browser you would get a missing template error as a GET request is going to expect to render a view, but that's a subject for another question. Basically, now you should understand what the controller actions are, how you get to them. If you want to learn more about what to do with your controller action, see the guide :)
I hope you understand what's going on now. Feel free to ask questions.
You want to use the Rails logging mechanism:
http://guides.rubyonrails.org/debugging_rails_applications.html#sending-messages
This means that even if you don't launch the server using rails s the output will still go to the right place.

Resources