Confused about how the render works in rails - ruby-on-rails

I'm still fairly new to rails, but I've been trying to figure it out by building a bunch of simple projects like blogs, forums, clones over the weekend.
One of the blogs that I'm working on is a typical blog with users(devise), posts, and comments. I've been following a tutorial for this.
The thing that I've been really confuse on is setting up the comments and rendering it.
The tutorial teaches me to make a partial for comment in the comment view named _comment.html.erb and then another for form _form.html.erb . I fully understand that to call the form i just do render 'comments/form' but for the comment.html.erb i need to render #post.comments how come it's not 'comments/comment'? Why is it comments with the S?
I've tried reading up on render and plurization on rails, but most of them just talk about the model.

There are two convention over configuration things going on here that may be causing you some confusion but are meant to save time.
Rails will automagically find the right partial if it follows naming conventions, meaning if your model is Comment that the view partial is located in app/views/comments/_comment.html.erb. That means you don't have to specify the location of the partial when calling render, but instead can just pass the model object directly and Rails figures out that you want it to render the partial and finds it on its own.
The reason it's comments plural here is that you are rendering all of the comments as a collection, not just a single comment. It's a convenience feature to allow the developer to simply tell Rails to render a collection and it will automagically know to use the corresponding partial. It's identical to typing:
#post.comments.each do |comment|
render 'comments/comment`, object: comment
end
Note how the above code is calling render directly on a model object so we don't have to bother specifying the location of the partial (again, assuming you followed the convention when naming and locating things). If we named the partial something else, then we'd have to specify the location like your other examples.

Related

How would I setup routing and partial loading for a rails application with a central dashboard?

I am having trouble figuring out how to make my rails app work with a central dashboard. Basically I want it to work so that when a user clicks on a course from the list, the details of the course are loaded into the dashboard. The ajax part isn't too complicated, I am however struggling slightly with loading the partial in when ajax isn't being used. I figure I can simply put some logic in the view so that if #course != null it will load the partial.
The routes are also giving me a bit of difficulty. So I wanted the url to resemble the following: dashboard/student/:id/university/:id/course/:id
I came up with the following, but is there a better way?
http://pastebin.com/keEmaznw
It's hard to understand your question. You've given us scant detail, and insufficient code. That said, regarding loading a partial with a nil object:
If you pass an object to a partial, Rails will take care of the rendering for you automatically, and no nil (instead of null, in Ruby talk) check is necessary:
= render #object
Regarding routes, yes, there is a better way: You should generally avoid nesting your routes more than two levels. This becomes a nightmare to test, and you end up writing very long method names:
edit_dashboard_student_university_course_path(#university, #course, #student)
You really don't want to be writing that in your view or your tests. think about it, if you want to edit a student, is it necessary to load the university and the course as well?

Should I use partial or show.html.erb?

I'm writing a web app containing posts and comments. Since there are many places I need to display a bunch of posts with their comments, I'm thinking about reusing the code. But I'm not sure if it is correct to use a partial _posts.html.erb that displays each post in #posts, or implement it directly through the show action in posts controller, and render this action when necessary in other views. Anyone has any idea?
For this use case, partials are your best bet.
As you said, there are many places I need to display a bunch of posts with their comments. A main premise of Rails is Don't Repeat Yourself. It is far more tidy (and programmatically sound) to retrieve #posts in your various controller actions and then render those posts/comments using partials in your views. Otherwise, you'd be rendering the show action within other views – views aren't really meant to render out actions, but the other way around, rather.
Yes, according to DRY principle your are thinking in a perfect manner, you should create a partial.
A good practice is instead of using #posts, you should pass posts as a locals like:
<%= render 'posts', posts: #posts %>
in this way you can use this partial from anywhere with providing just posts as locals without any dependency on #posts instance variable.

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'

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.

on Rails, how does form_for and validate_presence_of work hand in hand?

when we have validate_presence_of :name in the model and then when we put in the create action that we re-render 'new', then the form_for will populate the fields, and error_messages_for 'story' will have the correct error message.
this is really great, and and the same time, this looks like magic... i found that many books don't explain how the magic occur. is it by some global variable?
when the form_for is called... is it using the #story that came back from the #story.save, instead of the #story = Story.new from the new action? so if i use :story for the form_for, the fields won't be populated on error?
sometimes i feel that i am playing magic when using Ruby on Rails, except I don't know how the magic happens... kind of like if I make the rabbit appear, but I don't know how I did it. So I really want to know the inner workings of Rails.
Yes, Rails is very magical. Unfortunately these are just things that you have to learn to live with, and once you get used to the conventions you get to use the magic to do some very complicated things with great ease.
There are three separate issues here that are relatively simple individually but look very magical when you take it all in at once. Let's break them down one by one:
When validations fail, they disallow the model object from being saved and add errors to the object.errors hash.
When you run #story.save, it kicks off all the validations. Since #story.name is blank, validates_presence_of :name adds an error to the object.
Instance variables in the controller are available to the views they render.
So, yes, it is the same #story that the view has access to - the one that is invalid and has error information attached to it.
form_for takes many forms, and the one you're using is very smart
The form_for tag in your view probably looks like this:
<%= form_for #story do |story| =>
This is a special version of form_for that infers all kinds of information from the object passed in and renders the form appropriately. #story has some of its fields populated because of the line
#story = params[:story]
in your controller, so it goes ahead and fills in those fields for you. It does some other things, too - for example, it checks #story.new_record? to see if it should use the POST HTTP method (RESTful create) or the PUT method (RESTful update).
In summary, there are lots of little bits of magic to learn, but once you do the big magic is much easier to understand. Good luck!

Resources