How to add to_sentence to a :collection - ruby-on-rails-3

I have the following code that generates a list of superlatives:
<%= render :partial => 'superlative', :collection => #profile.superlatives %>
The :partial code referenced above is as follows:
<li class="superlative"><span title="<%= superlative.name %>">
<%= superlative.body %>
</span></li>
How can I add to_sentence to the #profile.superlatives collection? I tried:
<%= render :partial => 'superlative', :collection => #profile.superlatives.to_sentence %>
Doing so however makes the #profile.superlatives disappear from the view.
I looked at the docs but couldn't find an answer.

Ohhh, now I understand. Sorry for the confusion. Here's what I would do:
In your controller:
#superlative_bodies = #profile.superlatives.map &:body
# Equivalent to: #superlative_bodies = #profile.superlatives.map {|sup| sup.body }
In your view:
= #superlative_bodies.to_sentence
Some people would do this all in the view instead, which is up to you:
= #profile.superlatives.map(&:body).to_sentence
To explain, .map is a super-useful Ruby method that takes an array or other Enumerable and a block and returns a new array where each element is the corresponding element from the original array after the block has been applied to it. For example:
[ 'foo', 'bar', 'baz' ].map {|word| word.upcase } # => [ 'FOO', 'BAR', 'BAZ' ]
# or
[ 'foo', 'bar', 'baz' ].map &:upcase # => [ 'FOO', 'BAR', 'BAZ' ]
(The latter is just a shortened version of the former for when you only want to call the same single method on every element.)

Something like this, perhaps?
module ProfilesHelper
# ...
def superlatives_items (profile)
##acb ||= ActionController::Base.new # required to access render_to_string
profile.superlatives.collect |superlative|
acb.render_to_string :partial => 'path/to/partial/superlative',
:layout => false,
:locals => { :superlative => superlative }
end
end
# ...
end
# In view:
# <%= raw(superlatives_items(#profile).to_sentence) %>

Related

Nested Routing with a Collection in Rails

I'm getting an error: No route matches {:action=>"sort", :controller=>"links"}
I'm adapting from a non-nested example and am having trouble figuring out the nested routing.
Right now, my route looks like this:
resources :groups do
resources :navbars do
resources :links do
collection { post :sort }
end
end
post :add_user, on: :member
end
I am rendering a collection of links from navbar>show:
= render partial: 'links/link', collection: #navbar.links
and here's the collection, links>_link.html.haml:
%ul#links{"data-update-url" => sort_group_navbar_links_url}
- #links.each do |faq|
= content_tag_for :li, link do
%span.handle [drag]
= link.method_name
= link.code
= link.button
= link.text
= link_to 'Edit Link', edit_group_navbar_link_path(#group, #navbar, link), class: 'btn btn-mini'
= link_to 'Delete', group_navbar_link_path(#group, #navbar, link), data: { confirm: 'Are you sure?' }, method: :delete, class: 'btn btn-mini'
My links_controller has the sort action:
def sort
params[:link].each_with_index do |id, index|
Link.update_all({display_order: index+1}, {id: id})
end
render nothing: true
end
Because my link collection is being rendered from the navbar>show page, it's not clear to me where my sort action should be located (in links_controller or in navbars_controller).
And my navbars_controller defines #links:
def show
#links = #navbar.links.order("display_order")
respond_to do |format|
format.html # show.html.erb
format.json { render :json => #navbar }
end
end
Also here's the js for good measure (links.js.coffee):
jQuery ->
$('#links').sortable
axis: 'y'
handle: '.handle'
update: ->
$.post($(this).data('update-url'), $(this).sortable('serialize'))
Maybe this last line also needs work to include the route?
I'm using rails 3.2.

Kaminari support blocks?

Kaminari is great to create Twitter-like pagination:
=link_to_next_page(#results, t('kaminari.next'), :remote => true, :class => 'kaminari-next', :rel => 'next')
However, anyone has any idea to make it support blocks? I'd like to add a font-awesome icon:
=link_to_next_page #results, :rel => 'next', :remote => true, :class => 'kaminari-next' do
%i.icon-chevron-down.icon-2x
%br
=raw(t 'kaminari.next')
This doesn't seem to work.
I found the definition of the method by looking at the source code of Kaminari.
# A simple "Twitter like" pagination link that creates a link to the next page.
#
# ==== Examples
# Basic usage:
#
# <%= link_to_next_page #items, 'Next Page' %>
#
# Ajax:
#
# <%= link_to_next_page #items, 'Next Page', :remote => true %>
#
# By default, it renders nothing if there are no more results on the next page.
# You can customize this output by passing a block.
#
# <%= link_to_next_page #users, 'Next Page' do %>
# <span>No More Pages</span>
# <% end %>
def link_to_next_page(scope, name, options = {}, &block)
params = options.delete(:params) || {}
param_name = options.delete(:param_name) || Kaminari.config.param_name
link_to_unless scope.last_page?, name, params.merge(param_name => (scope.current_page + 1)), options.reverse_merge(:rel => 'next') do
block.call if block
end
end
This states that when you pass a block, the block content is what is displayed when there are no more results on the next page. So it seems it does not support what you are trying to achieve. Maybe you can add what you want displayed manually and then convert that code into a partial.

Tire and Elastic Search - Object Associations

I'm having a little difficulty with the Tire and Elastic Search functionality.
I have a Listing that has a Property. I'm trying to get a basic search form working so that I can create a query from the Property.
# listings/index.html.erb
<%= form_tag searches_listings_path, method: :get do %>
<p>
<%= text_field_tag :query, params[:query] %>
<%= text_field_tag :property_postcode, params[:property_postcode] %>
<%= submit_tag "Search", name: nil %>
</p>
<% end %>
At the moment, whenever I try filtering down the search results, it seems like the property_postcode is being ignored and all results are being returned.
# Listing.rb
include Tire::Model::Search
include Tire::Model::Callbacks
mapping do
indexes :id, type: 'integer'
indexes :title, boost: 10
indexes :description, analyzer: 'snowball'
indexes :posted_at, type: 'date'
indexes :property do
indexes :postcode, :type => 'string'
end
end
def self.search(params)
tire.search(page: params[:page], per_page: 5, load: true) do
query do
boolean do
must { string params[:query], default_operator: "AND" } if params[:query].present?
must { term "property.postcode", params[:property_postcode] } if params[:property_postcode].present?
end
end
end
end
def to_indexed_json
to_json(:include => {
:property => {
:only => [:postcode]
}
})
end
And finally for the property
#Property.rb
class Property < ActiveRecord::Base
belongs_to :listing, touch: true
after_touch() { tire.update_index }
end
Then finally
rake environment tire:import CLASS=Listing FORCE=true
Thanks in advance,
Ryan
Property.search(page: params[:page], per_page: 5, load: true) do
query { string params[:query], default_operator => "AND" } if params[:query].present?
filter :term, "property.postcode" => params[:property_postcode] if params[:property_postcode].present?
end
be sure to turn on routing in your mapping too
mapping :_routing => { :required => true, :path => property.postcode } do

can't pass locals to parital Rails

I have a partial _new_user_form.html.erb
<%= form_for(#user, :remote => true, :html => {:id => 'new_user_form'}) do |f|%>
<strong><%= :form_text %></strong>
<%= f.text_field :email, :placeholder => get_placeholder_text(#board), :size => "30" %>
<%= hidden_field_tag :role, role %>
<%=f.submit "SAVE", :class => "button-small" %>
<% end %>
In the show.rb I want to use it and pass in some partial variables as follows:
<%= render 'users/new_user_form', :locals=> {:role => "Celebrant" } %>
However I get this error:
undefined local variable or method `role' for #<#<Class:0x00000103d5e8b0>:0x00000103d5b930>
I read the documents about passing in locals and this seems correct. What am I doing wrong?
You're combining the short and long forms. Either of these are correct (identical):
render 'my_partial', :foo => 'bar'
render :partial => 'my_partial', :locals => { :foo => 'bar' }
I think you're calling render incorrectly. From the fine manual:
If no options hash is passed or :update specified, the default is to render a partial and use the second parameter as the locals hash.
So you end up going down this branch in the source:
view_renderer.render_partial(self, :partial => options, :locals => locals)
and that makes your call the same as this:
render :partial => 'users/new_user_form', :locals => { :locals => { :role => 'Celebrant } }
Note the extra level of nesting for :locals. Try this:
render 'users/new_user_form', { :role => 'Celebrant' }
I'm looking at (and using) 3.1 so your version might be a little different.

how to use urlhelper to include rails 3 custom data- attribute

I am using Rails 3 and found that if I add
:remote => :true, there will be added to the tag the data-remote = true attribute. But I can't find a way to add custom data- attributes to the urlhelper. The followings won't work:
<%= link_to projects_path, :history => "new"%>
<%= link_to projects_path, :data-history => "new"%> #this throws an error
<%= link_to projects_path, :data_history => "new"%>
What I want to generate is:
New Project
anyone?
What about:
<%= link_to 'New Project', new_project_path, 'data-history' => 'new' %>
( http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to )
This is an elegant solution:
<%= link_to "foo", foo_path, data: { foo: "bar" } %>