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.
Related
It's probably a dead simple question. Right now it uses the default application layout file. How can I create one just for AdminAdmin in order keep it separate from the one used on the main site?
Read layouts and rendering guide, there is paragraph about :layout option.
You can specify layout, or set it to false, to render without layout at all.
render :layout => 'special_layout'
render :layout => false
If my memory does not fail me again !! ;-)
this rails cast talk about this. But i'm not sure!
Anyway, if you never watched it. It's a good watch.
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.
I have a rails app I built for an old site I converted from another cms (in a non-rails language, hehe). Most of the old pages are mapped to the new pages using routes.rb. But there are still a few 404s.
I am a rails newb so I'm asking if there are any advanced ways to handle 404s. For example, if I was programming in my old language I'd do this:
Get the URL (script_name) that was being accessed and parse it.
Do a lookup in the database for any keywords, ids, etc found in the new URL.
If found, redirect to the page (or if multiple records are found, show them all on a results page and let user choose). With rails I'd probably want to do :status => :moved_permanently I'm guessing?
If not found, show a 404.
Are there any gems/plugins or tutorials you know of that would handle such a thing, if it's even possible. Or can you explain on a high level how that can be done? I don't need a full code sample, just a push in the right direction.
PS. It's a simple rails 3 app that uses a single Content model.
Put this in routes (after every other route that you have, this will capture every url)
match '*url' => 'errors#routing'
And now in errors controller in routing action you can implement any fancy logic that you want, and render a view as always (you might want to add :status => 404 to the render call). Requested url will be available in controller as params[:url].
There is an ugly way of doing this:
render :file => "#{RAILS_ROOT}/public/404.html", :layout => false, :status => 404
Maybe someone can come with a better solution.
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.
My software sends emails for users. I want to show them what the emails will look like before they get sent. However, with ActionMailer conventions, the entire template is in one file. This means the html,head,body tags, etc. Can anyone think of a good way to give my users a preview of what the emails I send out will look like?
Thanks!
I had the same issue. I built out the display with the associated model I was sending rather than in the mailer. I was able to feed sample data or live data to display it to the user.
when it came time to actually send it, I rendered the exact same thing within the mailer view
EDIT:
I apologize for the crap variable names in advance. I am not sure I am allowed to explicitly talk about them :)
Lets say I have a BarMailer function called foo(status,bar)
where status is a test email or a live email and bar is my associated model.
I called deliver_foo("test",bar)
deliver_foo sends out a multipart message so for each part I render_message and pass along variables I need. for example:
p.body = render_message('bar_html', :bar => bar, :other_data => bar.other_data)
so, that render_message is is saying to specifically use the bar_html view (I also have a bar_text for plain text).
this is the contents of my bar_html view:
<%=render :inline => #bar.some_parent.some_other_model.html, :locals => {:other_data => #other_data, :time => Time.now, :bar => #bar }%>
Its a little complicated, but it is based on a template system. By rendering inline everywhere, I am able to use the same code for a number of different functions including previewing and sending. I like this because it becomes a WYSIWIG. No extra code or functionality that could be buggy and muck with the potential output in an email. If it works in one area, it will work in the other. Plus keeping it DRY means I am not going to forget to modify a copy (which I would do frequently, hehe).