locals not working for controller rendering in rails 5.1 - ruby-on-rails

I have a controller action that renders a printable version of the page using a print.html.erb template. The controller code is:
def print
#title = 'Print - Drill'
render :show, layout: 'print', locals: { back_pth: drill_path(#drill) }
end
and in print.html.erb there is a line:
<%= link_to 'Back', back_pth, class: 'print_link' %>
but this generates an error:
ActionView::Template::Error:
undefined local variable or method `back_pth' for #<#<Class:0x007fd6004e1230>:0x007fd5f7da57d0>
The print template is called by many different controller actions, so how do I fix this? This code worked in rails 5.0.6.

As pointed out by FarazPantakar this is an issue in the rails 5.1 ActionController. The issue report has a workaround which is to use local_assigns in the html, so the link becomes
<%= link_to 'Back', local_assigns[:back_pth], class: 'print_link' %>

I am not very sure if this classifies as an answer but this might be what you're experiencing?
Perhaps, for now, you could move your code to the show action as that'd work even though it doesn't work inside the layout.

Related

rails doesn't render javascript with Gist Data within partial for ajax request for

I'm learning rails and facing some troubles with understanding following issue.
I have partial _answer.html.slim
Within partial I'm checking if link is gist and render gist
-if link.gist?
= javascript_include_tag("#{link.url}.js")
-else
= link_to link.name, link.url
The new link I'm adding with ajax request by calling create.js.erb
`$('.answer-errors').html('<%= render 'shared/errors', resource: #answer%>');
<% if #answer.persisted?%>
$('.answers').append('<%= escape_javascript(render #answer) %>');
$('#answer_title').val('');
<% end %>`
But by gist doesn't appear at all. It's only appear after refresh DOMe.
So why does it happen? And how to fix it?
So I tried to run ajax call within script but I think smth went wrong and I got 500

Missing partial comments/_comment in rails

I'm using a tutorial to get a feel for ruby, I am very much a beginner. Before posting this I have spent a couple of hours trying to resolve this myself with no luck. Sorry in advance if my explanation isn't great:
So I am getting this error screen:
error message
I am following a tutorial to make a basic reddit style app and I am trying to add the comments functionality.
When you render a collection like render #comments, Rails will check the type name of the items in #comments (i.e. 'comment') then look for a partial under app/views/comments/_comment.html.erb by default (note the plural singular distinction between the partial name and the folder/collection name).
The following steps should resolve your issue:
Create a comments partial under:
app/views/comments/_comment.html.erb
Now, when you call render #comments, each item of your collection is passed to the partial as a local variable as the same name without the underscore:
In _comment.html.erb
<%# comment is defined because it matches the name of the partial %>
<%= comment.<some_attribute_on_comment> %>

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

rails 3 - link_to to destroy not working

I am trying to create a destroy link to my users controller, I am also using devise.
Here is my code -
View
<%= link_to 'Delete User?', child, :confirm => "Are you sure you want to delete #{child.full_name}?", :method => :delete, :class => "user-additional", :style => "font-size:12px;font-weight:normal;" %>
Controller
def destroy
if #user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to account_index_path }
format.xml { head :ok }
end
end
end
Routes
devise_for :users
resources :users, :except => [:new]
The link translates to localhost:3000/users/10
When clicked this opens the users show instead of deleting them
Any ideas ?
Destructive actions should be performed as a form submission - http://www.w3.org/2001/tag/doc/whenToUseGet.html#checklist
use button_to (passing a :method => :delete) instead and style the button appropriately.
Actually I just had the exactly same problem yesterday
Try this:
<%= button_to "delete", your_object, :method=>:delete, :class=>:destroy %>
It works (for me at least)
In case that you are using jQuery instead of Prototype, you are probably missing a javascript file.
You can find details on how to add it to your project from the jquery-ujs GitHub page or from episode 205 of the Railscasts.
At a guess I think it is because in Rails 3, unobtrusive javascript is now used for functionality such as this (Rails 2 would output a bunch of nasty inline javascript for your code, Rails 3 puts the javascript in an external file, and uses HTML5 data- attributes to interact with that.)
To solve this you need to include <%= csrf_meta_tags %> in your page header to reference the external javascript. It also deals with XSS issues.
Some details here: Delete link sends "Get" instead of "Delete" in Rails 3 view
If you are using jQuery, make sure you have something like this:
<script type="text/javascript">
// this allows jquery to be called along with scriptaculous and YUI without any conflicts
// the only difference is all jquery functions should be called with $j instead of $
// e.g. $jQ('#div_id').stuff instead of $('#div_id').stuff
var $jQ = jQuery.noConflict();
</script>
follow the steps in the installation part rails/jquery-ujs
add <%= javascript_include_tag "application" %> in your layout file.
If you haven't included jquery and jquery-ujs in your app , the default link_to default coming with scaffold wont work!
I had the same issue.It got solved after including both these js!
Also if you get this problem in production mode, it may be because you have not compiled the assets. See http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets
Worked for me with confirmation message.
<%= button_to 'Destroy', {action: :destroy, id: version.id}, onclick: 'return confirm("Are you sure?")', method: :delete %>

Template path in Rails 3

Let's say, I connected the route / to WelcomeController's index action.
Inside of the index.html.erb-Template I want to display the path of the template from Rails.root upwards, ie.
<h1> We are rendering: <%= how_do_i_do_this? %></h1>
to render to
<h1> We are rendering: app/views/presentation/index.html.erb</h1>
In Rails 2 I could access template.path, but this doesn't work anymore
Any ideas?
Because of how template rendering works in Rails, you will now be able to use __FILE__ for this instead. This works for me:
<%= __FILE__.gsub(Rails.root.to_s, "") %>
There may be a better way to do this however, but I couldn't find it when I went looking.
Ryan's answer works. If you also want to put your method in a helper, use Kernel#caller. Here is a method I'm using to do something similar:
def has_page_comment? code = nil
if code.nil?
# grab caller file, sanitize
code = caller.first.split(':').first.gsub(Rails.root.to_s,'').gsub('.html.erb','')
end
...
end

Resources