Rails 3.1 partial fallback - ruby-on-rails

I don't quite understand why the new feature of partial rendering doesn't always kick in.
For example with this code:
= render(:partial => "pages/#{foo}/data")
it will never fallback to the partial pages/_data.html.erb if pages/test/_data.html.erb doesn't exist. How can I get this behavior?

Something you can do is :
= render(:partial => "pages/#{foo}/data") rescue render(:partial => "pages/data")
But I would be interested if someone has a better solution, this one is not elegant especially when you have some variables to pass to the partial. At least It can be better if handled by a helper.

My understanding of partials is not that they are small, standalone chunks of HTML to render, but rather bits and pieces of abstraction that you can use to organize your code in a more coherent manner.
As I see it, partials are created to be used in one or more places such that the file does not become cluttered, they're not used to simply be rendered by themselves. I could be mistaken, however.

Related

Can I Render A Layout Directly From routes.rb, Without A Controller?

I would like to set up a pair of style guides for the admin and public sections of a website.
Each will need its own layout which will contain a mixture of static html and calls to erb partials (so a static page won't cut it). I have no need of a controller(s) to serve these pages and I don't want what is effectively development-only content cluttering up the rest of the code. This got me wondering whether there is a way to render a layout directly.
Disclaimer: I appreciate this is not something I should do often/ever and I know there are a wealth of arguments for why this is a bad idea. I am interested in whether this is possible.
Is there a way for me to render a layout directly from routes.rb without going through a controller?
For some weird reason I wanted to render a blank JS file for a while, and writing a controller felt like too much for this kind of hack. Thanks to #genkilabs 's answer, I used this 3 liner:
get 'analytics/some_file.js', to: -> (env) do
[200, { 'Content-Type' => 'application/javascript' }, ['']]
end
I wanted to do something really stupid once, so if you do too, try this working example.
match :movedpage, :to => proc { |env|
if Rails.env.production?
#remote_path = 'http://productionhost.com'
elsif Rails.env.staging?
#remote_path = 'http://staginghost.com'
else
#remote_path = 'http://localhost:3000'
end
[
200,
{"Content-Type" => "text/html"},
[File.read("public/moved_page.html").gsub('#remote_path', #remote_path)]
]
}, :via => :all
Where moved_page.html was a static page asking people up update their bookmarks and #remote_path just typed in a link like #remote_path. Note that <%= %> won't work because you don't have view helpers in there.
So, theres enough rope to get yourself in trouble ^_^
Actualy the answer is NO, you can't do it without a controller. But see some trivial workaround...
It's not very fair but should work:
Assuming you have FooController with any logic you already have implemented. Now you want to render anypage.html.erb without creating any special controller. Here is how:
Configure a route to your static page:
get '/your/static/page', to: 'foo#anypage'
Implement the view app/views/foo/anypage.html.erb.
The problem is that it is impossible to change a path to your view. The path depends on the controller that you specify in a route (foo in the example). Also note that it will be rendered with a specified for FooController layout.
It should work by convention and you can read about it here.
UPDATE
Also I found very simmilar solution here. Using ApplicationController seems more reasonable for such pages. (Note that you needn't to create an action for it)

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.

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.

Is is possible to include views in a gem that the user can render as a partial?

Say I am making gem "awesome_o" and it will make apps awesome. How could I package up some view partials so that the user can optionally use them in his/her app for eg:
<%= render :partial => '#{some_path_to_awesome_o}/list_of_awesome' %>
Is that possible?
As I understand it, if you create an app/views directory in the base of your gem, Rails adds that to the views load path. So, create your partial at app/views/my_gem/my_partial.html.ext, and then render :partial => 'my_gem/my_partial' should work as expected.
As far as usage goes, though, I'd like you to include a simple helper method, too, since it'd be far easier for me to use and would allow you to change exact implementation later on. Even if it just calls render :partial internally, it'd produce a smoother experience.
Nowadays you could use an engine: http://edgeguides.rubyonrails.org/engines.html
As an alternative you could also make generators to create the views in the rails app, this would allow the users to alter the views to suit their needs.
I guess it depends on exactly what you are doing.

How to use in_place_edit plugin for rails with partials?

I am using the "in_place_editing" plugin for rails to render a form with in-place edits. Thing work fine as long as the default template is chosen by rails (no 'render' method is invoked inside the controller), but they break down when I try to render a partial using "render :partial => 'partial_name'" call. Is this a known issue (in_place_edit does not work with partials?) or am I missing something? I am getting the following error while rendering the partial:
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
.../vendor/plugins/in_place_editing/lib/in_place_macros_helper.rb:74:in `in_place_editor_field'
You don't provide anywhere near enough information in your question, giving only two lines of the backtrace and no fragments of the view which does work, or the partial which does not. This means that any attempts to answer you must be based largely on guesswork. That said, the in-place editor helper is just a helper method like any other, nothing special. You can call it from just about any view component. It is highly likely that the way in which that view is included by the controller, or indeed a parent view, is not the reason it is failing.
The helper method is complaining about a nil value. This means that most likely, your partial is invoking in_place_editor_field and passing it values which are not defined in the partial. Check to make sure it isn't using local variables which are not defined, compared to those used in the view where your in_place_editor_field call works; check to make sure that it isn't asking for different instance variables too. In all probability you'll find the views which work are using one variable name while the partial you've tried to render is using another.
The render :partial => ... mechanism supports different ways of explicitly passing in values to the partial; you may choose to use these to clarify your code. See the :locals and :object options for the "Rendering partials" section of the render documentation in the Rails API at:
http://api.rubyonrails.org/classes/ActionController/Base.html#M000658
I am working on a maintenance project which is in rails 2.3.8. And this issue ate a lot of my time
In the view, Change the view to have an instance variable:
#batch = batch
in_place_editor_field :batch, 'priority'

Resources