Render polymorphic form in partial - ruby-on-rails

I want to render a form for a comment in a partial called _feed_item.html.erb. This partial is used to display both Products and Requests, both of which have comments. The rendered comments form needs to be specific to which feed_item is being displayed (Product or Request).
I've created a gist to show what i've got so far. Please do let me know if anything is missing.
https://gist.github.com/aclel/82c332d9fd1a193694ef
Currently i'm able to create a link which takes me to the appropriate url to create a comment. This works well.
<%= link_to "Make Comment", new_polymorphic_path([#commentable, Comment.new]) %>
Instead of having to go to a different url, I would like to be able to render a form in the feed_item partial.

Related

Link to random record in header partial (rails)

I'm wondering how to create a "shuffle" button in the header partial of my rails app that links to a random record. I have a "pins" table and each pin is a video.
I've searched through stackoverflow and couldn't figure out how to do it..
I think it had to do with the header partial doesn't work with the Pins controller/model.
When someone clicks the button it should link to something like this:
website.com/pins/13
Any help would be great thanks!
EDIT:
This is the code I have previously tried:
offset = rand(Model.count)
rand_record = Model.first(:offset => offset)
But I am new to rails and I wasn't sure where to put it. I tried putting it in the model and the controller and both didn't work.
Ok, so I'm assuming that you want a link to a random Model to be shown each time a user loads a particular page. Let's say that the page that shows this link is the ModelController#index action.
Since the randomization only happens when the page is initially loaded, you can do it in the controller action:
class ModelController < ActionController::Base
#other actions
def index
#any other index code
#random_model = Model.order('random()').first
end
end
Now, in your view, you can link to that model in the usual manner:
<%= link_to("Shuffle", #random_model, :class => "btn btn-small btn-warning") %>
Every time that the controller action executes, it will pick a Model at random, and include a link to that Model when it renders the page.
Edited to address:
"Is there anyway to make it work without putting the code in the index and show actions?"
Yes. You can actually load the model right in the view code. Normally, assigning it to an instance variable in the controller is the 'more correct' method, but as you point out, it leads to duplication of code. If this is something you want to include in multiple views, I would recommend making it a partial. Something like so:
views/shared/_shuffle.erb:
<%= link_to("Shuffle", Model.order('random()').first, :class => "btn btn-small btn-warning") %>
And then rendering that partial in any page you want to include a randomized link:
<%= render 'shared/shuffle' %>
Note that if you render this partial more than once in a page, the random model will be different for each link.

Render html.erb (not partial) in other html.erb

I'm quite new to Rails and trying to make app with Foundation framework. The problem is with modal window.
I have an index.html.erb file in views/users folder, generated by scaffold.
Also there is a new.html.erb file in the same folder.
I want to open ../users/new link in modal window on index page.
I used examples in Reveal (Foundation Documentation), put new.html.erb file content in:
<div id="myModal" class="reveal-modal">
.
.
</div>
Also, add to New User link "href" attribute.
<%= link_to 'New User', new_user_path, 'data-reveal-id' => 'myModal' %>
as was described here.
Now I need to render new.html.erb in index.html.erb, cause I need this code just before /body tag, as described in Foundation Docs.
I've tried to render it as partial, but it doesn't work.
Is there any way to do it, without double new.html.erb as _new.html.erb and inserting it as partial in index.html.erb?
I don't think, that RoR with all there's "Write less code!" stuff, doesn't have the way for do it without code duplicating.
Thanks!
You cannot use the new action as it is, though you can put your form in one partial, use across new and your action to generate form in modal.
On Page load you can use _form partial.
You can use ajax to generate the form for the model if you want on fly, this can be use for edit as well as new.
Step1 :link_to "your action path", remote: true, id: "abc"
Step2: your action path should return html of the form using render to string
Step3: now using jquery ajax success of $("#abc") replace your model inner content with the form.
And use the create action for both ajax and postback.
Code is DRY.
Let me know if you need the code.
Thanks

Passing param using link_to and UJS

I'm having a hard time understanding the proper way to pass a param using link_to and UJS.
I have the following resources:
Photos
Comments
Users
A user is trying to comment on a photo by clicking "Add Comment." When this happens a box pops up using UJS showing a form rendered by utilizing a new.js.erb file. After "Create Comment" is posted the create.js.erb file is called to handle the update, which just hides the comment box and adds the comment to a list of comments.
In my index.html.erb for my photos I am doing the following:
I specify a link to add comments passing in the id of the current photo.
<%= link_to 'Add Comment', new_comment_path( photo_id: photo.id ), remote: true %>
This gives me the url: 0.0.0.0:3000/comments/new?photo_id=1, which is what I expect.
Now my question is, how do I handle this passed parameter in my new action such that I can specify something like
#comment.photo_id = photo_id
or
#comment.photo_id = params[:photo_id]
in my comments_controller.rb?
Is there something I can do in JS that will help me save the photo_id value to my #comment.photo_id column for the comment added?
First of all I'll suggest you to start using nested routes for things like comments or likes. You will find the railscast here nested_routes_railscast
Coming back to your question, use #comment.photo_id = params[:photo_id] in your controller.
There is a better approach to accomplish this, You can have the popup already on the photo show page. In the popup you can have a form for new comment model. After clicking on the specific photo you just have get the id of that photo using javascript and copy it into the hidden field for :photo_id in the form.
Yes, you can get photo_id in params, they way you have specified.
Suppose Photo has many comments in your case.
So in your case when in you get params[:photo_id] in comments_controller
you can do:-
#photo = Photo.find_by_id(params[:photo_id])
#photo.comments.create(params[:comment])
Please read about nested resources from guides.rubyonrails.org, so you can generate create comments route in restful manner.

Add section to form by rendering a partial when link is clicked

UPDATE 3:
For anyone who reads this, this is why it wasn't working as expected in update 2 below: Passing a local variable to a partial that is rendered after the view has already loaded
If anyone knows how to solve that issue, let me know please.
UPDATE 2:
I updated the javascript with the quotation marks and it partially works...in the sense that the javascript is now functional and it will cause a string of text to appear on the page when I click the link as long as I have the partial only contain a string of text. However, when the partial includes the form fields code, something goes wrong.
If I just paste the following render code directly into the form in the new.html.erb view, it produces a new form section properly.
<%= render "add_round", f: f %>
However, when I try to include similar code in comps_helper.rb and then reference it from the link_to, it does not work:
In comps_helper.rb:
def addRound(f)
render "add_round", f: f
end
In new.html.erb:
<%= link_to "render it!", addRoundLink_path, remote: true %>
<div id="some_id"></div>
And I changed addRoundLink.js.erb to:
$("#some_id").html("<%=j addRound(f) %>"); #Is this the correct change to have made here?
Clicking the link_to link does nothing in that case.
Any thoughts?
UPDATED CODE:
Thanks for the reply. I've made the following changes and it still does not appear to be working. The link appears at the bottom of the form but when clicked does not change anything. What am I missing?
routes.rb:
resources :comps
match '/new_competition', :to => "comps#new"
get "/addRoundLink" => "comps#addRoundLink", :as => :addRoundLink
Note: I included the other 2 lines related to "comps" just in case those would cause an issue.
comps_controller.rb:
def addRoundLink
respond_to do |format|
format.js
end
end
comps_helper.rb:
def addRound
render "add_round"
end
addRoundLink.js.erb:
$("#some_id").html(<%=j addRound %>);
comps/new.html.erb:
<%= link_to "render it!", addRoundLink_path, remote: true %>
<div id="some_id"></div>
Thanks.
ORIGINAL QUESTION
First off, I'm new to rails. I've read and tried many solutions to similar questions but nothing has worked so far.
I created a form with rails form_for and fields_for. The form creates a new competition (comp). The competition has many rounds. The top half of the form (the form_for section) accepts the details about the competition as inputs and the bottom half of the form accepts details about each round (the fields_for section). The form works perfectly in this basic format.
I took all the code that is in the fields_for section and put it into a partial. My plan was to then create a "add new round" link to the bottom of the form that would simply display the partial above the link each time the link is pressed. This would add a new section to the form for a new round and allow the user to input as many rounds as they'd like. This is the part that I am struggling to make work.
I added this code to my comps_helper:
def addNewRound
render "add_round"
end
This renders the file /views/comps/_add_round.html.erb.
My question is: how do I get this to render in the form when a link is clicked. As far as I can get with the research I have done is:
<%= link_to "Add new round", { }, :remote => true %>
I don't exactly know what is supposed to go in the {} that will execute the addNewRound method. And I don't know what, if anything, I need to add to my comps_controller file.
Thanks so much for the help.
You have to create an action in your controller
app/controllers/some_controller.rb
def hello
respond_to do |format|
format.js
end
end
and define a route to this action.
routes.rb
get "/hello" => "some#hello", :as => :hello
then create a link to this action like that:
<%= link_to "render it!", hello_path, remote: true %>
<div id="some_id"></div>
When you click this link it will find its way to your action and respond with js(javascript) because we told action to respond with only js.
At the end render the partial to anywhere you want in your view(*in this example to the some_id div*)
app/views/some/hello.js.erb
$("#some_id").html("<%=j addNewRound %>");
WARNING: Creating dynamic forms is a pain. You will face a lot of problems (like setting different ids for new form elements etc...). I highly recommend you to use ryan bates nested_form gem

Posting a form through popup in Rails

I have a model called Details, and two controller methods new and create. New method displays a form to create Details (in new.html.erb), which gets posted to the Create method that saves it. (when it succesffully saves, it it renders the new.html.erb file with the details.) This works as expected.
Now i want a separate page with a link to fill in these details. I want the click to do the intended work through a popup, example redbox. When you click on that link, a popup should show the form, whose submit should post the form, and if it is successfully done, then refresh the original page. If the post is unsaved, then the same form should show the errors. What do i need to do to make it work in Ror? I guess i need some stuff to go in new.js.rjs and maybe create.js.rjs, but i can't really figure out what to put in those files.
Redbox updates the page's dom to add a div at the end of it. So your form is a part of the main page.
So if you add a form tag in this redbox, all your page will be reloaded as there's only one.
So you add anywhere in your page (preferably at the end) :
<div id="redbox" style="display: none;">
<%= form_for #details do %>
# Whatever form fields you want here
<% end -%>
</div>
You do a link that'll open the redbox :
<%= link_to_redbox 'Open The Details Form', 'redbox' %>
This will display your redbox with your form.
And as it is the same page, not a new windows, when you'll validate your form, it'll reload the all of it.
I used a link_to_remote_redbox for this, which on clicking, fetches the form rendered by the new method call in a popup widnow. it submits to the create function and it is now working. actually i had previously made it work without ajax and i was having difficulty in making it work with ajax. the problem was solved once i made separate partials for ajax calls, and doing:
respond_to do |format|
format.js { render :template => 'detail/ajax_template'}
...
end
I provided different templates for both create and new method calls, used the :html => {:id => 'some-id'} in form and the :update => {:some-id} to replace the form with the message that it worked correctly.
So I didnt know that i needed separate templates for the different styles of forms, and that i needed to use the :update option to replace the form when i asked the above question.

Resources