No results with pg_search from search form (Rails 3.1) - ruby-on-rails

Good day!
I use pg_search to implement Full text searching in my web app. I created form where user print his data and then i try to show it but result always empty! What is wrong?
/views/users/index.html.erb
<%= render 'shared/search_form' %>
<%= will_paginate %>
<ul class="users">
<%= render #users %>
</ul>
<%= will_paginate %>
/views/shared/_search_form.erb
<% search_id_attr = :q %>
<%= form_tag( users_path, :method => "get" ) do %>
<%= label_tag( search_id_attr, "Search for:" ) %>
<%= text_field_tag( search_id_attr ) %>
<%= submit_tag("Search", :name => nil ) %>
<% end %>
/controllers/users_controller.rb
class UsersController < ApplicationController
...
def index
#title = "All users"
#users = PgSearch.multisearch( params[:q] ).paginate( :page => params[:page] )
end
...
end
UPD1: After editing in /controllers/users_controller.rb I have params[:q]. Now i get such error:
ActionView::Template::Error (Missing partial pg_search/documents/document with {:handlers=>[:erb, :builder, :coffee], :formats=>[:html], :locale=>[:en, :en]}. Searched in:
* "/Users/iUser/rails_projects_terminal/sample_app/app/views"
):
6: <%= will_paginate %>
7:
8: <ul class="users">
9: <%= render #users %>
10: </ul>
11:
12: <%= will_paginate %>
app/views/users/index.html.erb:9:in `_app_views_users_index_html_erb__3107215974202561754_70174719087800'
UPD2: I created empty partial views/pg_search/documents/_document and now i just don't have any results.

I'm the author of pg_search.
You ought to rename your variable from #users to #pg_search_documents, because PgSearch.multisearch always returns objects of type PgSearch::Document, not User.
Then you will want to do something like this in your view:
<%= render 'shared/search_form' %>
<%= will_paginate %>
<ul class="users">
<%= #pg_search_documents.each do |pg_search_document| %>
<%= render pg_search_document.searchable %>
<%= render #users %>
</ul>
<%= will_paginate %>
This is because multisearch was designed for searching across multiple models.
If you want to make a search that only searches User, then you should instead use pg_search_scope to build a search scope directly on the User class. For example:
class User < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_name, :against => [:name]
end
User.search_by_name("ExR") # => returns an Active Record scope of `User` objects.
Let me know if this isn't clear. I know that the documentation has grown a bit large and should be simplified and organized so that developers have a better chance of understanding the subtleties.
Thanks!

params[:Search] will contain the name of your submit button. I think you meant params[:q]. Try that.

Related

Connect Multiple Yields in Rails

Rails Newbie. Be gentle. If I need to show more stuff I'll do it.
Trying to insert a newsletter signup block above my footer on a project but didn't make it a partial in the layouts set up.
I have the yield outputting an index from a blog.
Right now it's just saying "false" on my local host.
Is it possible to have multiple yields to different indexes?
Is it possible to insert another page into a layout page?
application.html.erb
<div id="blog">
<%= yield %>
</div>
<div>
<%= content_for?(:newsletter) ? yield(:newsletter) : yield %>
</div>
<div>
<%= render 'layouts/footer' %>
</div>
newsletter.html.erb
<% content_for :newsletter do %>
<h1>Get My Awesome News Letter</h1>
<p>Give me your email and keep up to date on my cat's thoughts.</p>
<%= form_tag('/emailapi/subscribe', method: "post", id: "subscribe", remote: "true") do -%>
<%= email_field(:email, :address, {id: "email", placeholder: "email address"}) %>
<%= submit_tag("Sign me up!") %>
<% end %>
emailapi_controller.rb
class EmailapiController < ApplicationController
def newsletter
render params[:newsletter]
end
def subscribe
gb = Gibbon::Request.new
gb.lists.subscribe({
:id => ENV["MAILCHIMP_LIST_ID"],
:email => {:email => params[:email][:address]}
})
end
end
routes.rb
root to: 'posts#index'
get "/:newsletter" => 'emailapi#newsletter'
post 'emailapi/subscribe' => 'emailapi#subscribe'
You shouldn't need this conditional test:
content_for?(:newsletter) ? yield(:newsletter) : yield
try just:
<%= content_for :newsletter %>
Here's the doc on content_for:
http://apidock.com/rails/v4.2.1/ActionView/Helpers/CaptureHelper/content_for
Ie only show the newsletter if newsletter is present.
The extra yield (if newsletter-content is not present) is repeated from the blog-section above.
You probably shouldn't have duplicate plain yields just the one... everything else should have a name (eg :newsletter)
Also - you seem to be missing an <% end %> in newsletter.html.erb
You should be able to just use another render block. I'm not sure where your newsletter.html.erb lives, but if, for example it lived in a folder such as includes/ you could do something like:
<%= render 'includes/newsletter' %>

RoR Rnder a partial cant find method

I have a classes User and Company, I want to re-use the users partial as the to render company staff.
In my CompaniesController I have:
def staff
#company=Company.find(params[:id])
#users=#company.works_fors.paginate(page: params[:page], :per_page => 10)
#title=#company.name+" staff."
end
And in my staff.html.erb template I have:
<% if #users.any? %>
<ul class="users follow">
<%= render #users %>
</ul>
<%= will_paginate %>
<% end %>
This is the works_fors/_works_for partial:
<%= render :partial => 'user' %>
Which Renders
<li>
<%= gravatar_for user, size: 50 %>
<%= link_to user.name, user %>
<% if current_user.developer? && !current_user?(user) %>
| <%= link_to "delete", user, method: :delete,
data: { confirm: "You sure?" } %>
<% end %>
</li>
However this throws an error on the user object as it cant find the method
undefined local variable or method `user' for~~
I think this is because Im calling the user object from within companies but there is a defined relationship, or do I need to redefine in companies ?
It's hard to tell, but it appears that what you call #users in your controller is in fact not a User collection, but a WorkFor collection.
#users = #company.works_fors...
What you mean is:
#works_fors = #company.works_fors...
This means that staff.html.erb is working with a works_for collection. So you should rename the variable in your template to avoid confusion.
# staff.html.erb
<% if #works_fors.any? %>
<ul class="users follow">
<%= render #works_fors %>
</ul>
<%= will_paginate #works_fors %>
<% end %>
Now we know we are rendering a works_for partial. So an instance of works_for is be available inside the partial. We need to ask it for its associated user instance, and pass it to the render method.
# works_fors/_works_for.html.erb
<%= render works_for.user %>
As a bonus, you can save yourself some queries by preloading the users.
#works_fors = #company.works_fors.includes(:user)...

Rendering a partial in rails. Specifying the partial for a resource gives an error, but not specifying a partial works fine. What gives?

I've got this working now quite accidentally, but I don't understand what causes it to break when I explicitly specify what partials are to be used for rendering the resource/s. Can anyone explain it?
The index template for my Posts controller contained the following line, which was giving me an error:
<%= render partial: 'posts', collection: #posts %>
The error (in my browser) said:
NoMethodError in Posts#index
Showing /Users/applebum/Sites/rails_projects/eventful2/app/views/posts/_posts.html.erb where line #1 raised:
undefined method `any?' for #<Post:0x000001064b21f0>
Extracted source (around line #1):
1: <% if posts.any? %>
2: <div id="posts">
3: <% posts.each do |post| %>
4: <%= render partial: "posts/post", locals: { post: post } %>
Changing the problem line to
<%= render #posts %>
made the error disappear and the posts appear (displayed nicely in markup from the appropriate partials) as I had wanted and expected them to.
Here's my _posts.html.erb partial:
<% if posts.any? %>
<div id="posts">
<% posts.each do |post| %>
<%= render partial: "posts/post", locals: { post: post } %>
<% # render :partial => "comments/comments", :collection => post.comments %>
<% end %>
</div>
<% end %>
And the _post.html.erb partial it's referring to, if that matters:
<div class="post" id="post_<%= "#{post.id}" %>">
<div class="post_inner">
<%= link_to avatar_for(post.user, size: "small"), post.user.profile %>
<div class="post_body">
<div class="user-tools">
<% if can? :destroy, post %>
<%= link_to '<i class="fi-x"></i>'.html_safe, post, :method => :delete, remote: true, :class => "delete", :confirm => "Are you sure you want to delete this post?", :title => post.content %>
<% end %>
</div>
<h5 class="username">
<%= link_to post.user.name, post.user.profile %>
<span class="timestamp">• <%= time_ago_in_words(post.created_at) %> ago</span>
</h5>
<div class="content">
<%= post.content %>
</div>
<ul class="foot">
<li>Like<li>
<li>Share</li>
</ul>
</div>
</div>
</div>
And the relevant bits from the controller:
class PostsController < ApplicationController
respond_to :html, :js # Allow for AJAX requests as well as HTML ones.
before_filter :load_postable
load_and_authorize_resource
def index
#post = Post.new
#posts = #postable.posts
end
private #################
def load_postable
klass = [User, Event].detect { |c| params["#{c.name.underscore}_id"] } # Look for which one of these there's a ***_id parameter name for
#postable = klass.find(params["#{klass.name.underscore}_id"]) # Call find on that, passing in that parameter. eg Event.find(1)
end
Can anyone explain to me what's going on here? I couldn't find anything in the Layouts and Rendering guide at rubyonrails.org.
Thanks!
Your error comes from assuming :collection and #posts mean the same thing when rendering. From Rails Docs (point 3.4.5):
Partials are very useful in rendering collections. When you pass a collection to a partial via the :collection option, the partial will be inserted once for each member in the collection
So, if you use that, for each post, you will be doing post.any? which fails as any? isn't defined for a single post.
From the same docs, you should check if render returns Nil to see if the collection is empty:
<h1>Posts</h1>
<%= render(#posts) || "There are no posts." %>
PD: Use the partial to render only one post, not all of them.
GL & HF.

RoR Ransack Searching issue

I have two different controllers (scholarships_controller, scholarships_browse_controller) that look at the scholarship model. I want my Ransack search function to show the search results on the current page. So, for example, if I am on /scholarships_browse and I use the search functionality, I want it to use the scholarships_browse_controller and show the results on /scholarships_browse.
Currently, if I search on /scholarships_browse it uses the scholarships_controller and redirects to /scholarships to show the results (instead of /scholarships_browse).
Code for ScholarshipsBrowseController and ScholarshipsController
def index
#search = Scholarship.search(params[:q])
#scholarships = #search.result.page(params[:page]).per(3) #allows 3 scholarships on a page at a time
#search.build_condition
respond_to do |format|
format.html # index.html.erb
format.json { render json: #scholarships }
end
end
Code for scholarships browse index.html.erb:
<%= search_form_for #search do |f| %>
<%= f.condition_fields do |c| %>
<div class="field">
<%= c.attribute_fields do |a| %>
<%= a.attribute_select %>
<% end %>
<%= c.predicate_select compounds: false, only: [:cont, :eq, :gt, :lt] %>
<%= c.value_fields do |v| %>
<%= v.text_field :value %>
<% end %>
</div>
<% end %>
<div class="actions"><%= f.submit "Search" %></div>
<% end %>
So, I guess specifically I'm asking how do I make sure I am using the ScholarshipsBrowseController index instead of ScholarshipsController index when I am on /scholarships_browse ?
On your view:
<%= search_form_for #search, url: RAILS_ROUTEHERE do |f| %>
...
<%- end %>
search_form_for its an extension for form_for, so you can use the :url parameter to tell the form what should be the action of it (you can check the page source code when you render it on browser, you can check the tag <form action=""> to make sure it points to the right route.

Rails 3 tagging problems, acts_as_taggable_on

I'm using acts_as_taggable_on to add tags to posts, other tagging plugins/gems don't work with rails 3. I can edit/display tags on the post model and the tags controller displays the posts tagged by name i.e /tags/post-tag-name/.
The functionality I want is to turn the tags on the posts pages into links to display the other posts with the same tag.
I followed the tutorial in sitepoints 'simply rails 2' which uses acts_as_taggable_on_steroids but I'm stuck with the following error;
ActionView::MissingTemplate in Posts#show
Missing partial acts_as_taggable_on/tags/tag with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml], :formats=>[:html], :locale=>[:en, :en]} in view paths "../app/views"
Extracted source (around line #28):
25: <div id="tags">
26: <% unless #post.tag_list.empty? %>
27: <p class="tags">
28: <%= render :partial => #post.tags %></p>
29: <% end %>
...
class Post < ActiveRecord::Base
...
acts_as_taggable_on :tags
end
class TagsController < ApplicationController
def show
#post = Post.tagged_with(params[:id])
end
end
_tag.html.erb
<%= link_to, tag_path(:id => tag.name) %>
posts/show.html.erb
<div id="tags">
<% unless #post.tag_list.empty? %>
<p class="tags">
<%= render :partial => #post.tags %></p>
<% end %>
</div>
Also trying to add a tag cloud at tags/index.html as described here http://github.com/mbleigh/acts-as-taggable-on gives me a routing error of;
No route matches {:action=>"tag", :id=>"news", :controller=>"tags"}
Looks like you want to use :collection, which will render the whole list with the template:
<div id="tags">
<% unless #post.tag_list.empty? %>
<p class="tags">
<%= render :partial => 'tag', :collection => #post.tags %>
</p>
<% end %>
</div>

Resources