Adding dynamic fields to nested form through AJAX - ruby-on-rails

I've been watching and reproducing these railscasts on my app: 196-nested-model-form-part-1 and 197-nested-model-form-part-2. I do not yet have a pro account so i can't watch the revised episode.
I'm developing under rails4 (edge) and link_to_function has been deprecated in favor of unobstrusive JS (which is great).
I'll keep the example of the above railscasts (i.e. survey/question).
What i'd like to do is to use the question's partial through unobstrusive javascript and i just don't know how and where i should do this.
I was thinking of two ways to do so :
First way would be to add in my app/assets/javascripts a file surveys.js with the function add_question but i don't see how i could use my partial from here.
Other way would be to create a new action in my SurveyController that would respond using the question partial but i'm bothered by the fact of having an action specific to questions in my survey controller.
I can't help to think there must be a better way to do this.

Did you know about remote links and forms? You can use a remote link here to accomplish what you want.
In your view:
link_to 'Add question', add_question_path(#survey), remote: true
In your controller
def add_question
#survey = Survey.find(params[:id])
respond_to do |format|
format.js #add_question.js.erb
end
end
The last step is to create a file app/views/surveys/add_question.js.erb
$('#my_survey').append('<%=j render partial: 'my_question_partial' %>')
Don't forget to create a route for your ask_question_path
For more info about remote links and forms see: http://tech.thereq.com/post/17243732577/rails-3-using-link-to-remote-true-with-jquery-ujs

I don't have a pro account on Railscasts either, but sometimes it is a good idea to have a look at Ryan's Github account. Oftentimes he develops gems to stuff he covered in his episodes. There you will find this awesome nested_form gem, which does exactly what you want.
Of course you can reinvent the wheel, but I think it is much easier and faster to use Ryan's gem. The documentation explains perfectly how to use it. Have fun!

Related

Confused about how the render works in 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.

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.

in-place edit in Rails 3

There are a few options for editing a model in-place while in the Show page, i.e. without having to load a form in the Edit page. For example, see http://www.ruby-toolbox.com/categories/rails_in_place_editing.html.
Has anyone had any experience using any of these options (or others) in Rails 3? Any pointers or advice?
In my case, I have a fairly long form composed of a variable number of items. From a usability point of view, it makes good sense to edit the text in these items in the same page, instead of needing an Edit button for each one that sends the user to an edit page for the particular item.
Excellent question!
in_place_editing is by dhh, Rails creator. It's maintained by the Rails core team. So it certainly should be looked into.
Hobo is a large framework that features in-place editing front and center. It's a smooth package but may be more than what you want or need.
Updated for Rails 3
Ryan of Railscasts recommends the Best in Place gem. See the Railscast with sample code and more info.
Sure it makes sense to me. I do it all the time.
For example, I am working on a complex polymorophic nested model form and it only has two views. An index, and a partial for dynamically adding more attributes to it.
If you know AJAX, that can really help your UI in that your users will not even have to click a save button.
To accomplish a bare minumum of this. Set up an index.html.erb with your form inside it.
In your controller, you could specify your actions like so :
def update
#quick_fact = #organization.quick_facts.find(params[:id])
if #quick_fact.update_attributes(params[:tab])
flash[:notice] = 'Text Tab was successfully updated.'
redirect_to quick_facts_organization_path(#organization)
else
render :action => "index", :id => params[:id]
end
end

Rails user authorization

I am currently building a Rails app, and trying to figure out the best way to authenticate that a user owns whatever data object they are trying to edit.
I already have an authentication system in place (restful-authentication), and I'm using a simple before_filter to make sure a user is logged in before they can reach certain areas of the website.
However, I'm not sure the best way to handle a user trying to edit a specific piece of data - for example lets say users on my site can own Books, and they can edit the properties of the book (title, author, pages, etc), but they should only be able to do this for Books that -they- own.
In my 'edit' method on the books controller I would have a find that only retrieved books owned by the current_user. However, if another user knew the id of the book, they could type in http://website.com/book/7/edit , and the controller would verify that they are logged in, then show the edit page for that book (seems to bypass the controller).
What is the best way to handle this? Is it more of a Rails convention routing issue that I don't understand (being able to go straight to the edit page), or should I be adding in a before_find, before_save, before_update, after_find etc callbacks to my model?
check out the following gems:
cancan
devise
authlogic
and don't miss Ryan's great railscasts on the above
this will give access to anyone who changes the value in the address bar
#book = Book.find(params[:id])
but if you go through the association of the logged on user rails (ActiveRecord) will automatically update the sql query
#book = current_user.books.find(params[:id])
of course this assumes that your books table has a user_id column
You may need an authorization plugin. I had some experience use this plugin a while back. This article also has an overview:
You might also take a look at Declarative Authorization
Hey I have recently done this myself. The easiest way to do this is to have the edit feature display on the page but incase it in a method such as the following:
<%if current_user %>
<% if current_user.id == wishlist.user_id %>
<div id="text3"><%= link_to 'Edit', edit_wishlist_path(#wishlist) %></div><br />
<%end%>
<%end%>
Is this what you were hoping for?

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.

Resources