Use Render template instead of render action by default in rails controller - ruby-on-rails

I'm trying to implement the following behavior:
You can see that i have pretty standart views structure for controller, but instead "actions" partial, i created folder which is named like an action and in them i have a partials for actions.
I Try use "prepend_view_path":
def set_view_paths
self.prepend_view_path ["#{Rails.root}/app/views/#{controller_name}/#{action_name}"]
end
But rails finds next:
Missing template "posts/index"
in ".../app/views/posts/index"
I need to add somthing like that in the end of the action:
render template: 'index'
Question:
Is there a more beautiful way to solve this problem?

Checkout this SO thread. From reading the thread it doesn't look like there is a clean way for you to solve this problem. The only way would be to override render.
I'm not sure why you are putting your template files into subfolders but, if it is not providing you with any benifit, it's probably easier to move index.html.erb, show.html.erb ect out of their subfolders and just put them under views/posts.
This will also make it easier for other developers (and yourself, later on) because you are conforming to Rails conventions.

Related

Where is the code of rails doing rendering and layouts?

I am working on a project which involves understanding the mechanism of how rails does rendering and layouts, including, where does rails know that it needs to do rendering (either by a render statement or default rendering), which view file it is going to render, how is view file nested together, how does rails merge the layouts with the view file, how does rails decide which layout file to use for a specific render statement. I hope there are some existing code module I can use to produce such rendering results, so I don't have to write code to mimic this process myself.
Backing what the Tin Man said, I'm gonna do my best to answer this as 'How does rendering views work'
First you create a controller....
rails g controller welcome index
This creates the welcome controller with the action index
By action, I mean if you look inside the new welcome controller you will see
def index
end
That's where all the variables and stuff go that you need inside of that 'page' for example if you need to print out all the users, you would do this
def index
#users = User.all
end
Now, inside of /config/routes.rb, when you typed in rails g controller welcome index it generated a route something like this
get '/welcome/index' => 'welcome#index'
What that does, is when someone goes to the URL http://localhost:3000/welcome/index Rails will point to the welcome controller and render the index action
What that will do is tell rails, 'HEY, theres an action called index, go look in /views/welcome and make sure there's a file called index.html.erb
That WILL be there because when you generated the controller, it generates the views for the actions you specify, in this case we only specified index.
Now Rails knows what controller to look in and what action and html to render.
That's pretty much the basics :)
Hope this helps!

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.

Scaffold default files are the best practice?

Hey, i have some experience with MVC. but I'm new to rails. I'm using the scaffold command to generate some default files. The model looks clean and nice, but the controller and the views aren't really dry. The contents of new.html.erb and edit.html.erb are almost the same and the methods new/edit and create/update are doing almost the same thing. In other frameworks i've used only one view for updating and creating new entries and also the same method in my controller by setting the id as an optional parameter. Do they use this structure to keep things RESTful (i have not much of a clue about rest :()? Is it the best practice to use this default stuff for crud?
The scaffold generator is a pretty good place to start. As you pointed out, there are some things which are not that great about it. I think most people take what the scaffold generates and then fix it up to their liking. For example, you can extract the form part from new.html.erb and edit.html.erb and place it in a partial _form.html.erb. Then update new.html.erb and edit.html.erb to include that partial to render the form. I think that for Rails 3, the scaffold generator has been changed to do this by default.
It does seem like new and edit, and create and update are pretty much the same, but you need to remember that they are mapped to different HTTP methods and URLs, which ties in to the whole RESTful resource idea. Check out the RailsGuides for routing, the section CRUD, Verbs, and Actions has a nice table of the seven different routes and the differences between them.
You should check out ryanb's nifty-generators:
http://github.com/ryanb/nifty-generators
The scaffolding creates a partial view called _form that then gets referenced from the new and edit views. It also comes with a bunch of other nice options -- like generating your views in haml or your tests in Shoulda or RSpec.
If they wanted you to keep it they wouldn't call it "scaffolding." It's just there to make everything work out of the box. If you put it into production you will more than likely be laughed at.

Two controllers for one shared view in Ruby on Rails

I have two controllers for two respective models, by example, photos and categories. index and show methods are very similar in each controller, and the views are identical. What is the best method for share the view by the two models?
I've though two options:
Use a helper. In the helper will put the code for the view, and will call the helper from each view (photos/views and categories/views)
Use a partial in each views. I think it's a more clean solution, but I see huge DRY's in my mind when going to code this solution.
So, I have two controllers from two models, each one at and exposes a #photo object (photos controller with all the photos, and categories controller with just the selected categorie's photos) and I need one view to show both.
I'm looking for an elegant solution for this, complaining REST and DRY principes. Any idea?
Thanks in advance.
I have a similar situation with one of my projects. All the delete views for most controllers are styled the same way, display the same confirmation boxes, and simply renders a predictable display of whatever object is being deleted.
The solution was quite simple and elegant in my opinion. Simply put, what we (the developers) did was create a new directory in app/views called shared and put shared views in there. These could be full template files or just partials.
I would suggest using a shared template (in neither categories nor photos view directories, but rather in the shared directory) and rendering it manually from the view.
e.g. have a method as such in both controllers and a file app/views/shared/photo.html.erb:
def show
#photo = Photo.first # ... or whatever here
render :template => 'shared/photo'
end
This should successfully render the shared template. It is the DRYest route and doesn't have the feeling of pollution you get when using a more-or-less empty view in each controller's view directory just to include a shared partial, as I understand your question is suggesting.
About the first answer:
If the partial must be rendered from a view:
<%= render :partial => "shared/photo" %>
and the partial must be in app/views/shared/_photo.html.erb
I'd use an helper because they are shared among views. For the HTML part, I'd use partials so it would be a mix of both ways.
This looks like a good use case for the Cells gem.
#bjeanes If all your delete views are the same, you can create views/default/delete.html.erb and all the delete actions will use it.
That's what i'm doing: Most of my views are on default, and i create specific ones only when needed
Update: Ok, this post is from 2009, anyway, i will keep my comment here in case someone gets here from Google like i did.

Resources