Ruby on Rails - Call controller method from a view - ruby-on-rails

Sorry, I have a Rails newbie question. In my Rails application, how can I call a method defined in my controller from the view? For example, let's say I wrote a custom method that retrieves stock information. In my view, I want to have a regular HTML button, that upon clicking, will call my custom method and populate the stock results.
How is that done? I've looked around and couldn't find a straightforward way to do this. But I'm sure I'm missing something here.

Edit: I took the question by its title which wasn't what the question was. The answer to the title of your question is at the bottom
What you want is an ajax request, which is a separate controller action. You'll need:
javascript to request a route and populate its DOM object when the button is clicked
an action that returns whatever the ajax request was asking for
There are many ways to do this, but if you search for "howto rails ajax" you'll find a gazillion tutorials to help you on your way. One way that I like is called pjax: https://github.com/rails/pjax_rails
Old answer...
Declare a helper_method, like so:
In your controlller:
private
def find_stock
...
end
helper_method :find_stock
In your view:
<% find_stock.each do |stock| -%>
Documentation: http://api.rubyonrails.org/classes/AbstractController/Helpers/ClassMethods.html#method-i-helper_method

You can check the documentation for the button_to view helper
This is one way, of course, you could use the remote option to do this via an AJAX request.

Related

Ruby on rails button that will not redirect to another page but does it's action on the same view

before anyone get's mad I would like to start by apologizing by how stupid it may seem to some but i'm really having a hard time finding out how.
I have been looking through tutorials online on how to program in ruby on rails but I can't seem to find out how to make a button that does it's action and won't redirect to another page. For example when I want my program to count the number of people present in my database I need to make another view where the action would be executed. I would like to make it do the action on the same view and not redirect to another page.
Every tutorial that I've gone through only redirects the action to another page.
Could anyone please help me? Thanks in advance.
Suppose that you want to have that button in an index page of some controller. If you add something like this (I'm using HAML here):
= link_to "Something"
Then clicking the link will refresh the page but calling the index method of your controller again before rendering. Now the only problem is to figure out if the index method has been called by clicking on the Something link or just by calling the page? You can do this by passing some parameters (e.g. ?mylink=true) when clicking the link.
HOWEVER I personally prefer to implement a custom controller method (via routes.rb) and then redirect to the desired page (e.g. index). Something like this:
routes.rb
resource :my_resource
collection do
get "test"
end
end
my_resource_controller.rb
...
def test
# Do stuff
redirect_to action: "index
end
my_resource/index.html.haml
= link_to "Something", text_my_resource_path
Now clicking on Something link gets you to test method and after doing your stuff you are redirected back to where you were (i.e. index). Read more about redirect_to HERE.

Rails 3 update two models using ajax

I've been stuck on this for about 2 weeks. I need help in the proper way to do this. I have two models. Model one is Leads. Model two is Referrals.
Leads belongs_to referrals
Referrals has_many Leads
In the Lead entry screen there is a partial that displays possible Referrals for the lead to select from. There is an Add Referral link in the partial that brings up a modal using twitter bootstrap as the css framework. From that I am rendering the New action of the Referral controller.
This all works up to this point. What I want to have happen is that I can then enter a new referral, it is saved, the modal closes, and the list of referrals in the partial of the Leads edit/new view is then updated to reflect the new referral that has been added. But at this point I now have nested form_for's. As well as a Referral form that is working off a different controller.
I am not sure how I should approach this. I have been searching and trying various methods for a couple of weeks now. Do I repeat myself and completely rebuild the Referral view and controller under the Leads controller and view? Repetitive code like that is why I switched to rails, and why I feel I'm not looking at this correctly. There has to be a simple way around this. I have looked at using Gems like Draper and Cell, and I've read up on using presenters. But those seem to all be solutions for a dashboard type of view, not what I am trying to accomplish.
Any help or direction would be much appreciated.
Thank you...
This is the way i program this kind of problem.
It works for me, maybe you can adapt to your own situation.
Well, you create action on yout Referral Controller should respond with javascript.
if #referral.save
format.js
This way, you will have a create.js.erb file whitin the views folder where you keep your referral's views.
In the create.js.erb you may have something similar to this:
$('#modal_id').hide(); // Hide the modal or if you prefer, remove from DOM.
$('#referral_list_id').chidren().delete(); // Remove the list of referrals.
$('#referral_list_id').html(
"<%= escape_javascript(render('referrals_list')) %>"
); // Render a partial with the new content from your controller.
Your form for a new referral inside your modal, should be remote too:
<%= form_for #referral, :remote => true do %>
Maybe you will run into some gotchas while implementing this way, but i believe it is kinda easy to solve.

What's the best way to do UJS in rails when you have a re-usable widget?

In my current project I have a couple instances where I have a re-usable form that exists inside a rails partial. This form submits to a specific controller via ajax (:remote => true). The controller does some stuff and then returns back the appropriate js.erb to modify the page via javascript.
This works fine for when I have a single view. But the problem seems to happen when this re-usable partial exists on multiple views. In view 1 I might want to issue a completely different set of javascript commands then in view 2.
As a concrete example, say I have a comments controller that has the normal CRUD operations.
I now have partial called _comments_box.erb. This _comments_box.erb contains the ability to submit a comment via a simple line:
- form_for comment, :url => post_comments_path(post), :remote => true do |f|
This submits to a comments_controller.rb create method which looks somethings like this:
def create
... do some stuff, like create a new comments model
respond_to do |format|
# will respond with create.js.erb
format.js
end
end
The create.js.erb in turn adds a comment to the view, perhaps doing a bunch of other updates to the DOM.
Say I render the _comments_box.erb within a view called post_summary.erb. Now I have another view, post_detail.erb that requires the same _comments_box.erb. However the post_detail.erb requires me to update completely different divs on the DOM in response to a new comment.
I need to create a different JS response for each instantiation. So I can either:
Create an alternate controller method, say create_2. Pass in some parameter to the _comments_box.erb from post_detail.erb to the _comments_box.erb partial so it knows which controller method to fire. This will allow me to have a separate file _create_2.js.erb that will allow me to manipulate the post_detail.erb view independently.
Forget about using js.erb altogether and just use plain old AJAX and get back JSON, and handle the javascript manipulation completely on the client-side.
It seems option 1 allows me to continue to use the UJS supported by Rails which is nice. But also means I probably will be adding a lot of duplicate code everywhere which is annoying. Is there a way for me to do this elegantly while continuing to use UJS?
That's exactly the purpose of Apotomo: http://apotomo.de/
Here is it's own description:
Apotomo is a true MVC widget framework
for Rails. Widgets are based on Cells
and provide reuseable view components.
Having bubbling events, they know when
and how to update themselves via AJAX!
Working with Apotomo widgets almost
feels like developing GUI components –
in a Rails environment.
Have a try, it's great.
I'd not recommend using UJS for frontend apps: server shouldn't take care of client side business. I agree it's useful and clean but it lacks performance and thus should be kept for backend stuff (RJS will move into a gem, see here: http://weblog.rubyonrails.org/2011/4/21/jquery-new-default).
That said, back to the solutions you expose:
1) I think you won't need an extra controller, you'd just have to pass additional params in order to know from where to query came from. A hidden_field could do the trick. With this info, render the good js.erb file
format.js { if condition
render "create.js.erb"
else
render "create_2.js.erb"
end
}
2) I'd go for it and return json but you'll face the same problem: knowing from where the request comes from.
A better solution (than using a hidden_field) might be to check the request.referer in your controller action. This way you leverage the fact that each context has a unique URL, and don't have to explicitly specify another unique value when rendering your widget partial.

How do I move something in Rails?

I'm a programming noob, and learning Rails. I'm making a GTD webapp for fun, and I'd like to make a "done" section. In other words, I have a link that says "Done!" and I want that to move the current task into a done page, instead of index.html.erb. All I know about Rails is what was in the official beginner tutorial.
It sounds like you want to set a property like 'completed' on a task. There are a lot of things that have to happen for this to work
Your task model needs to have a property like 'completed'
Your controller needs to have an action to mark as completed (you can possibly just use the standard 'update' action..)
You need to have a route to that action
Your view needs to call that action

Doing an action in Rails without changing site

Good day...
Still a beginner question. I mostly asking to save myself hours of trial and error... I had those already and there was no result.
What I wanna do... I have a controller that has an action, of course. I want to send this action two IDs, it should make some database entry of those. No problem, the action works well.
But I don't want a view to it, I want the user to click on a link and not even leave the site. Ideally there should be some Ajax (using jQuery a lot on the site) that changes the link to a 'Thanks' or anything.
So yes, my main question is: How can I activate an action of an other controller without leaving the site, from a link. Long intro, but I hope you can give me some hints.
Take a look at link_to_remote for the view side and then you can just have your controller function render nothing => true.
To keep it un-obtrusive & return something from the controller action... I think you probably want something like:
def my_action
# your code... e.g. #model = Model.find(params[:id])
render :json => { :whatever => #model.whatever }
end
In your javascript, do what thou wilt with the returned information & prevent the default action of your hyperlink by returning false or using jQuery's prevent default functionality for the click event.
Look up link_to_remote method in rails. That should make an ajax call out to a controller function and not leave the page.

Resources