Rails outside controller rendering i18n - ruby-on-rails

I'm trying to render a view outside of a controller and can't seem to get i18n to work. I'm using the feature noted here, https://github.com/rails/rails/issues/18409, https://evilmartians.com/chronicles/new-feature-in-rails-5-render-views-outside-of-actions, https://api.rubyonrails.org/classes/ActionController/Renderer.html
ABCController.render :index, assigns: {myvar: '12345'}
This is an example of what I'm doing. The view renders fine in English and Spanish when accessed normally through a controller. I'm actually using that render command inside another controller action to pass it to WickedPDF. However, it always renders English.
Any help would be appreciated. I looked through the documentation for render and https://github.com/rails/rails/issues/18409 this pull request.

I couldn't try this, but it can solve your problem.
I18n.with_locale('es') do
ABCController.render :index, assigns: { my_var: '12345' }
end

Figured it out. I wasn't setting locale for the one action I needed it. It was a stupid oversight on my part. It works just fine with I18n localization as long as you do it correctly. Make sure all controller actions are properly localized and render works fine. I thought I had my bases covered but I clearly didn't.

Related

Ruby on Rails routes to controllers

As I understand it, routes will take you from a starting point to a controller, and an action. The action brings up the associated views; so what if I don't need any views for my controller, and just want to just call a controller's underlying method, without rendering the view or route.
Lets say I have a FoodsController with several methods, and there exists methods cake, pizza, and chips within that controller. Each one queries the database for a secret message and stores it in a variable, but the request for this is going to come from some other part of our application.
To accomplish this am I supposed to use a route for this or some kind of dot syntax such as food.cake().
So I guess what I am trying to say is, hey "Server" go do this and come back to where you left off once its done.
Controller are only for URL endpoints. For example if you hit http://my.app/my_route, you need to map the my_route part to a controller action in your routes.rb file. But what happens if you type this into your browser? You'll want to see something right? So you need to return some data (json, html, erc). You can use render for this.
This is different to writing 'normal' Ruby code, i.e. Ruby outside a web framework. Do you understand what a class is and how the following works?
class MyClass
def initialize
end
def my_method
puts "my_method_called"
end
end
MyClass.new.my_method # => "my_method_called"
This is very basic Ruby and works in Rails as well, although there are some rules about where code needs to be written.
By the way, if you really want to make a controller action that renders nothing, just use:
render text: "", status: 204
return false
The status: 204 means "No Content".
You can use render json or text, if the method does not render anything, I think it should be private.
In your example you could use the cake method in another controller like so:
cake = Food.cake
Please note that this method should live in the food model and not the controller, since you do not need a view.

How best to setup rails with only one view?

I'm working on a personal RoR project with an interesting sort of problem: the whole app only needs one HTML template.
Basically, the whole app is presented through HTML5 canvas (it's going to be a game of sorts). But I'd still like there to be URLs for accessing specific resources, such as '/player/1'.
So what's the best, DRYest way to do this? I'd really hate to specify the template in every action in the controllers.
render :file => "layout_file", :layout => false
You could define your view in app/views/layout/application.html.erb and leave all the others empty, but that wouldn't avoid the reloading of pages.
You should also have all your methods respond in json format.
Or just an old good:
render :nothing => true
at the end of your methods.

Rails redirect without changing URL

I've some piece of ruby/rails code.
In one of the controllers say foo i have an action doo which does something and I want to redirect to another controller say bar and action say dar.
When I use redirect_to then URL in the address bar changes to /bar/dar while if I use render then I don't know how to render another controller's view.
I am using rails 2.3.5 so render_component is unavailable for use (which i found could be really really useful for me) -- so as a shortcut if you have any idea of alternate for render_component that will help me infinitely.
Any ideas?
[If am unclear please ask me details]
Instead of a real redirect, could you use an AJAX call to hit the action and pull in the appropriate views?
You can render the same partial from both views. You'll have a view for each action and in each of the views you'll have something like <%= render :partial => "partials/form" %>.
You can just call the action (like calling a function) and then render the template. But accordingly to the MVC pattern you should manage your controller-side logic on the controller and then loads the propper view.

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.

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