How to access view helpers from RJS helpers in Ruby on Rails? - ruby-on-rails-3

I had some common bits of RJS that I was repeating in multiple RJS files, and so wanted to put it into a helper.
I added a method to app/helpers/application_helper.rb just like I would normally for an html.erb file. The method works, except that it can't call view helpers that the RJS file could.
One of the lines that worked in the RJS file was:
notices = flash.collect { |type,msg| content_tag(:p, msg, :class => type) }
But content_tag is not accessible from the RJS helper. Why not, and how do I access it from there?

what about something like this?
#application_helper.rb
def view_helpers
ActionController::Base.helpers
end
def do_it
view_helpers.content_tag :div, :class => 'yes'
end
You have to use view_helpers in any method you call from rjs too, which is not very nice, but I tried it in the model (got projects only in 2.3 and 3.1) and that worked...

Related

How do I render a reply into turbolinks 5 with rails 5

I have a controller action where I'd like to receive form data, execute some business logic, then refresh the form. This works Ok if I save the object in the database then use a redirect_to. I would prefer the controller edit the object in memory and render the response directly.
For example, take a standard rails 5.1.4 generated app generated like so:
rails new turbolinks_example
rails g scaffold Thing name
rails db:migrate
The form, slightly edited for brevity and to enable turbolinks:
<%= form_with(model: thing) do |form| %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name, id: :thing_name %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
A) Now we edit the controller to change the object. This uses a redirect to edit and works:
ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.update name: "#{#thing.name} is OK"
redirect_to edit_thing_path(#thing)
end
end
B) This uses a render and does not work:
class ThingsController < ApplicationController
...
def update
if #thing.update(thing_params)
#thing.name = "#{#thing.name} is OK"
render :edit
end
end
end
With A)
- Update request is received by controller
- Object is modified (& saved)
- Redirect is returned
- Rediredted url is rendered
- DOM is updated
With B)
- Update request is received by controller
- Object is modified (in memory)
- Response is rendered
- Response is received by browser, but ignored
The response received, looks correct. Full HTML, with the changes made to the object. How do I get turbolinks to notice it and replace document.body like normal?
The full project, including development.log is on Github
The problem is that, in Rails 5:
Forms are remote by default: they are sent via AJAX unless local: true provided
When rendering HTML as a response to an AJAX call, nothing happens unless, of course, there is custom javascript in the client handling the response
Turbolinks is enabled by default, which handles redirect_to properly, but does nothing for render
I think this is an inconsistency in Rails that causes much confusion, such as the problem you exposed with your code. I created a gem turbolinks_render to deal with this problem. I also wrote a little post on this very same problem.
I hope that, one way or other, this gets fixed in future Rails versions.

Use a custom helper in Middleman Frontmatter

my Middleman structure looks like this:
source/
blog/
post-one.md
post-two.md
blog.erb
index.md
my config.rb defines this helper:
helpers do
TOP_LEVEL_DIR = Dir.pwd
def posts
files = Dir["#{TOP_LEVEL_DIR}/source/blog/*"]
files.map do |file|
created_at = `git log --follow --date=short --pretty=format:%ad --diff-filter=A -- #{file}`
basename = File.basename(file).split('.')[0]
{
date: created_at,
link: '/blog/' + basename,
title: basename.gsub('-', ' ').capitalize
}
end
end
end
And my blog.erb looks like this:
<ul>
<% posts.each do |post| %>
<li><%=post[:date]%>: <%= link_to post[:title], post[:link] %></li>
<% end %>
</ul>
This works really well for me, but I'm missing one thing. I want to display the created_at metadata that I've defined in my custom helper in the layouts for post-one and post-two.
Usually this is done by defining Frontmatter, but I don't want to manually input the dates of each post when they are available in git.
So I need a way to define a custom helper that allows me to access the current_page meta data. Or some other way to pass in the metadata I'm manually creating in the posts helper into the layout.
This was much more straightforward than I thought it would be. current_page is available in helpers, so I can use it directly in my helper like this in config.rb:
helpers do
def created_at
# `git log --follow --date=short --pretty=format:%ad --diff-filter=A -- #{current_page.source_file}`
end
end

Call FactoryGirl.create for all rspec controller tests?

is there any way you can load some factories for all controller tests? I've got a few of them which are necessary for all controller tests (menu items) and I don't like putting them all in controllers seperately. Not very DRY :)
Thanks
Maybe you can take a look at rspec's shared context, highlighted here: https://www.relishapp.com/rspec/rspec-core/v/2-11/docs/example-groups/shared-context
Create an RSpec macro.
Using user as the Factory you want to use, here's an example you'd put in spec/support/controller_macros.rb:
module ControllerMacros
let!(:user) { FactoryGirl.create :user }
end
In your spec/spec_helper.rb include the macro for controllers:
RSpec.configure do |config|
config.extend ControllerMacros, :type => :controller
end
The let! is like let as if it was referenced in a before block.
The ControllerMacros is also a handy place to add things like a sign_in method, etc.
You can also put shared examples in spec/support as well.

customize kaminari pagination template

I'm having difficulty customizing the default kaminari template.
I've used the generator to create kaminari template files. In kaminari/paginator.html.haml:
= paginator.render do
%nav.pagination
All I want to do is access the actionview helpers within this, like link_to, or render. I've searched the source code and I can't find any incline of the helper being passed to this render method.
Essentially, being able to do this:
= paginator.render do
%nav.pagination
= render :partial => 'custom links'
= link_to "custom link", custom_path
..would solve my problems.
I didn't get a satisfactory answer, and so I'll submit my own solution.
Helpers cannot be used in the paginator.render block.
So, first I generate kaminari custom template files:
rails g kaminari:views default -e haml
Create a new file kaminari/custom.html.haml with the contents:
#pagination
= paginate custom
= render :partial => "kaminari/custom_view_file"
Replace kaminari paginator helper (paginate #results) in your view file with:
= render :partial => "kaminari/custom", :object => #results
You should be able to do something like this:
# /app/views/kaminari/_paginator.html.erb
= paginator.render do
%nav.pagination
= render :partial => 'shared/custom'
= link_to "custom link", custom_path
Basically, you need to provide the full path of the partial as it probably does not reside in the same directory.
EDIT:
I think Kaminari does not import rails view helpers in the paginate.render block in _paginator.html.erb.
To customize the output generated by paginator, you should instead
1. customize the _next_page.erb.html and so on where you can use rails helpers. I don't know why it is so though.
2. If you want to display some common html as a part of paginator, I suggest you put it in layout instead. Paginator is about navigation of pages.
For example, this is the _prev_page.html.erb:
<span class="prev">
<%= link_to "google", "www.google.com" %>
<%# link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, :rel => 'prev', :remote => remote %>
</span>
I just commented out the old code and used a custom link.
Just met the same problem.
My solution:
= paginator.render do
%nav.pagination
= render :partial => 'custom links'
= #template.link_to "custom link", custom_path
As partial rendering occurs in scope of Paginator, there is possibility to use its instance variable, pointing to template (see https://github.com/amatsuda/kaminari/blob/master/lib/kaminari/helpers/paginator.rb)
Little hacky, but works.

render :inline => "<%= yield %>" not working

I'm upgrading from Rails 2.3.8 to 3.0.3 and notice that my code for nested layouts isn't working.
In my main Application layout I have the line
<%= controller.sub_layout %>
which then looks to the controller, who has:
def sub_layout
render :inline => "<%= yield %>"
# or otherwise some partial for the sub-layout
end
The problem is, this doesn't get rendered! If I put a direct <%= yield %> statement in the layout, it does work. So the question is, what's happening here, and how do I fix it?
This worked beautifully in Rails 2.3.8
How about a much saner approach:
render :layout => false
Related: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render
So you all have some more of a background on this, the whole sub-layout approach was based on this blog post: Sorta Nested Layouts (The solution is given in the comments section.)
Instead of making a controller method sub_layout, any controller that uses a sublayout needs to define a before_filter method that sets a variable:
def inner_layout
#inner_layout = 'layouts/sublayout_partial_name'
end
then in the main layout.html.erb (i.e. application.html.erb), where you would otherwise put your yield statement:
<%= #inner_layout ? render(:partial => "#{#inner_layout}") : yield %>
the assumtion is that the sublayout partial file will have its own yield statement in there somewhere.