call controller with ajax in rails - ruby-on-rails

In ruby on rails project, when I create a reporter successfully, page is redirect to another action from another controller; and when the page is redirect, the page is reloaded. In this project, I have 2 controller:
reporters_controller.rb:
class ReportersController < ApplicationController
layout "reporter"
def new
#reporter = Reporter.new
#gomrokaddresses = Gomrokaddress.find(:all)
end
def create
#reporter = Reporter.new(reporter_params)
if #reporter.save
#redirect_to new_reporter_path
redirect_to new_problem_path(:id => #reporter.id)
else
#existreporter = Reporter.find_by(params[:rep_user_name])
redirect_to new_problem_path(:id => #existreporter.id)
end
end
problems_controller.rb
def new
#reporter = Reporter.find(params[:id])
#problem = #reporter.problems.build
end
def create
#reporter = Reporter.find(params[:id])
#problem = #reporter.problems.build(problem_params)
if #problem.save
redirect_to new_problem_path(:id => #reporter.id)
else
redirect_to new_problem_path(:id => #reporter.id)
end
end
reporter.rb
class Reporter < ActiveRecord::Base
has_many :problems
end
problem.rb
class Problem < ActiveRecord::Base
belongs_to :reporter
end
I create reporter and problem with form_for in view. When I complete form_for in new.html.erb (for reporter) and submit, create action (that exist in reporter_controller) is called, and then if information are true, page is redirect to /problems/new. Because of this redirect_to, the page is reload; I don't want reload the page, just when I create the reporter, the form_for of reporter replace with the form_for of problem. How can I do this?

Try this in your controller
redirect_to new_problem_path(:id => #reporter.id), format: 'js'
Hope this helps!

A controller action renders the corresponding view template by default. Here, the action "problems#new" automatically renders "views/problems/new.html.erb".
In your code, you've redirected to the URL represented by new_problem_path, and a GET request to that URL is routed to the "problems#new" action. Thus, the action is invoked and its template is loaded.
However, there are ways to override this default behavior if you want to call the action without loading the view template.
Also, redirect_to is different from AJAX. For AJAX, you'd use something like
def create
...
respond_to do |format|
if #reporter.save
format.html { redirect_to ... }
format.js
else
format.html { render action: ... }
format.js
end
end
end
and then add the option :remote => true to form_for in the form that you use to create the new reporter.
But I'm not sure if this would accomplish what you're trying to do. Could you please explain your question further?

Related

Tree comments Ruby on Rails

Trying to implement a tree-like comments on the site via a gem - acts-as-commentable-with-threading.
Comments are excellent and are displayed on the site when I visit a site under the user (implemented via the gem devise).
But when trying to view pages anonymously, naturally, I receive an error that id is not may be due to the elements onto a blank.
This is my controller recipes_controller.rb:
class RecipesController < ApplicationController
before_action :authenticate_chef!, except: [:index, :show]
def show
#recipe = Recipe.find(params[:id])
#comments = #recipe.comment_threads.order('created_at desc')
#user_who_commented = current_chef
#new_comment = Comment.build_from(#recipe, #user_who_commented.id, "")
end
...
comments_controller.rb:
class CommentsController < ApplicationController
before_action :authenticate_chef!
def create
commentable = commentable_type.constantize.find(commentable_id)
#user_who_commented = current_chef
#comment = Comment.build_from(commentable, #user_who_commented.id, body)
respond_to do |format|
if #comment.save
make_child_comment
format.html { redirect_to(:back, :notice => 'Comment was successfully added.') }
else
format.html { render :action => "new" }
end
end
end
...
recipe.rb:
class Recipe < ActiveRecord::Base
acts_as_commentable
...
In views (recipes/show.html.erb) I put this render :
<%= render partial: "comments/template", locals: {commentable: #recipe, new_comment: #comment} %>
I think that you may need in the controller to create something like a design if ... else for those who just browse the site, because the default at this point in the show method is set current_chef, because of what and error.
You need to handle the special case in view(probably comment template) for anonymous visit. Cause then current_chef would be nil. So where you're using it in view and controller, handle that properly.
A tip: You don't need to assign current_chef to any instance variable actually. It's already a helper method. You can call it directly from view.

Issue with before_filter

Please help me try and understand what is happening here:
I need to approve a nested snippet but when I do it says it cannot find book. I think it may be an issue with the routes because the URL in the browser doesn't match the rake routes.
If someone could hold my hand and explain this as you would to a child :)
Couldn't find Book without an ID
Below is the controller with snippets#approve and the before_filter.
class SnippetsController < ApplicationController
before_filter :authenticate_user!
before_filter :find_book
def create
#raise params.inspect
#snippet = #book.snippets.create(params[:snippet])
#snippet.user = current_user
if #snippet.save
redirect_to #book
flash[:success] = "Snippet submitted and awaiting approval."
else
flash[:base] = "Someone else has submitted a snippet, please try again later"
redirect_to #book
end
end
def approve
#raise params.inspect
#snippet = #book.snippets.find(params[:id])
#snippet.update_attribute(:approved, true)
redirect_to admins_path
end
def edit
#snippet = #book.snippets.find(params[:id])
end
def update
#snippet = #book.snippets.find(params[:id])
respond_to do |format|
if #snippet.update_attributes(params[:snippet])
format.html { redirect_to #book, notice: 'Comment was successfully updated.' }
else
format.html { render action: "edit" }
end
end
end
private
def find_book
#raise params.inspect
#book = Book.find(params[:book_id])
end
end
Now I understand that since I'm doing a post my rake routes says this.
/books/:book_id/snippets/:id(.:format)
Here is the routes for the custom route:
active_snippet POST /snippets/:id/activate(.:format)
This is my custom routes for book && snippet :approval
post "books/:id/activate" => "books#approve", :as => "active_book"
post "snippets/:id/activate" => "snippets#approve", :as => "active_snippet"
I've currently got this in my browser ../snippets/2/activate
Erm.... Not sure if I'm thinking correctly.
You're sending a POST request to snippets/:id/activate which calls snippets#approve.
There is a before_filter on the entire SnippetsController that calls find_book which executes #book = Book.find(params[:book_id]). Because your path is snippets/:id/activate, params[:book_id] is nil and hence you are getting that error.
You need to either change your snippets#approve path to include the book_id, or pass the book_id as a POST param so that your before filter has access to it.

Rendering new form for a nested Ruby on Rails Resource

In my Ruby on Rails application, each group has_many :expenses. I have nested my routes, so expenses are entered only as child entities of their parent groups. Here's an excerpt from routes.rb.
resources :groups do
resources :expenses
end
I cannot figure out how to render the 'new' action in the case of an expense not saving when it is submitted through /groups/:group_id/expenses/new. In my expenses_controller.rb, here is how the create action is defined:
def create
#expense = Expense.new(params[:expense])
#expense.group_id = params[:group_id]
if #expense.save
redirect_to group_expense_path(#expense.group.id, #expense.id)
else
render 'new'
end
end
Everything works fine if I satisty expense validation and #expense.save winds up working. However, when it fails and the code tries to render 'new' I get:
undefined method `expenses_path' for #<#<Class:0x007fd408b1fd58>:0x007fd408f21ca8>
So, I am assuming I have something about my nested routing wrong. How do I return the user to the new form but still display to him/her through the flash[] params the errors with the data they originally attempted to submit?
The problem is that #group is not initialized
So in your controller just do
#expense = Expense.new(params[:expense])
#group = Group.find(params[:group_id])
#expense.group_id = #group.id
Looks like you need to explicitly specify the url for form_for in your view.
Something likeā€¦
<%= form_for #expense, :url => group_expenses_path(#group.id) do |f| %>
...
<% end %>
In your <%= form_for %> you have used #group for url, because expenses belongs_to groups. But inside your create action in the controller you have not defined what is #group, so first you should define it as:
#expense = Expense.new(params[:expense])
#group = Group.find(params[:group_id])
#expense.group_id = #group.id
Also I would suggest to use respond_to in your controller:
respond_to do |format|
if #expense.save
format.html { redirect_to group_expense_path(#group.id, #expense.id), :notice => "Any msg you want" }
else
format.html { render :action => "new" }
end
end
All of these are in your create action inside the controller.
Also for different rendering methods look up: http://guides.rubyonrails.org/layouts_and_rendering.html
Hope this helps!

Destroy method has stopped working

I have two models: page and authors, when i choose the destroy method it just returns the show page. The models are linked by telling the model that the author has_many :pages and the page belongs to many :author.
this is the code for my page controller:
class PagesController < ApplicationController
def index
#pages = Page.find(:all, :order => 'created_at DESC')
end
def show
#page = Page.find(params[:id])
end
def new
#page = Page.new
end
def edit
#page = Page.find(params[:id])
end
def create
#page = Page.new(params[:page])
if #page.save
redirect_to(#page, :notice => 'Page was successfully created.')
else
render :action => "new"
end
end
def update
#page = Page.find(params[:id])
if #page.update_attributes(params[:page])
redirect_to(#page, :notice => 'Page was successfully updated.')
else
render :action => "edit"
end
end
def destroy
#page = Page.find(params[:id])
#page.destroy
end
def author
#pages = #author.pages
end
end
Where should I be looking to solve this problem, when i hit destroy it semds me to the page to destroy but nothing more, no :notice appears it just seems to not have the destroy method.
Thank you
I don't know what you mean by
choose the destroy method
But I'm assuming you're just accessing the pages/:id url in your browser? This is the show action as you said.
In order to actually destroy your model (ie. access the destroy action in the controller) you need to send a DELETE to /pages/:id.
This is usually accomplished using something like:
<%= link_to 'Destroy', #page, :confirm => 'Are you sure?', :method => :delete %>
Note the :method => :delete. This will actually send a DELETE to the controller (assuming you've got your rails.js included to take care of this) and thus map to the destroy action instead of the show action
Have you disabled JavaScript in your browser? :)
A couple of things to look at:
It's not clear what type of HTTP request you are sending to your application. The fact that the show action seems to be triggered makes me think that your request is an HTTP GET method. If you want the destroy action to be invoked, make sure it is an HTTP DELETE method.
Have you checked your database to see if the ActiveRecord had been destroyed? It could be that you are not seeing any notice simply because you are not setting a flash notice message. For example:
def destroy
#page = Page.find(params[:id])
flash[:notice] = "Page successfully removed"
#page.destroy
# You may also want to have a redirect here, e.g. redirect_to #pages
end
On a separate note, not sure what you are trying to achieve with the author method in your controller but it doesn't look right. It's not restful and it seems to return an array of pages rather than an author.

How to delete a specific post from a model in rails?

Since, I am new to rails, so I have want to know a small functionality.
I have a reports model in my rails 3 application(not by scaffolding). I am displaying reports one by one through ajax functionality. I want to add a delete link to my each report. I have also created the destroy method in my controller. Now, I don't know how to delete a specific report when I click on the delete link of that particular report.
Here's my controller code:-
class ReportsController < ApplicationController
def index
#reports = Report.all(:order => "created_at DESC")
respond_to do |format|
format.html
end
end
def create
#report = Report.create(:description => params[:description])
respond_to do |format|
if #report.save
format.html { redirect_to reports_path }
format.js
else
flash[:notice] = "Report failed to save."
format.html { redirect_to reports_path }
end
end
end
def destroy
#report = Report.find(params[:id])
if #report.destroy
format.html { redirect_to reports_path }
format.js
end
end
end
You can assume that my reports are being displayed in the twitter-timeline format and I want to add the delete report feature to each report. Please help me out.
In your view you'd add a link, button, etc. to send the delete action back to the server.
Using link_to for example:
link_to("Destroy", report_path(report), :method => :delete, :confirm => "Are you sure?")
You can do the same with button_to.
Update:
Sorry I missed the AJAX mention (thanks Jeffrey W.).
You'll also want to add :remote => true if you want to send the delete via AJAX.

Resources