doing an OR with ransack (rails) - ruby-on-rails

I have these two inputs:
<%= search_form_for #search, url: search_path, method: :post do |f| %>
<%= f.text_field :thing_false %>
<%= f.text_field :thing_null %>
<% end %>
and when they're both set to "t", I get this query executed:
SQL: SELECT "stuffs".* FROM "stuffs" WHERE (("stuffs"."thing" = 'f' AND "stuffs"."thing" IS NULL))
How do I make it so I get this executed?
SQL: SELECT "stuffs".* FROM "stuffs" WHERE (("stuffs"."thing" = 'f' OR "stuffs"."thing" IS NULL))
The ransack documentation doesn't really address this. This is the closest example that I can find:
>> User.search(:first_name_or_last_name_cont => "Rya").result.to_sql
=> SELECT "users".* FROM "users" WHERE ("users"."first_name" LIKE '%Rya%'
OR "users"."last_name" LIKE '%Rya%')

If you don't want the user to have to select the "any" option, you can make it so that the search always uses "OR" by adding something like this in your controller:
#search = User.search(params[:q])
#search.combinator = "or"
#users = #search.result
You can also create different groupings of search fields and specify the appropriate combination within the grouping. The controller could have something like:
#search = User.search(params[:q])
(0..1).each do |index|
#search.build_grouping unless #search.groupings[index]
#search.groupings[index].combinator = "or"
end
#users = #search.result
And the view could have something like:
<%= search_form_for #search do |f| %>
<% #search.groupings.each.with_index do |grouping,index| %>
<%= f.grouping_fields grouping do |g| %>
<% if index == 0 %>
<%#= fields for first grouping here %>
<% end %>
<% if index == 1 %>
<%#= fields for second grouping here %>
<% end %>
<% end %>
<% end %>
<%= f.submit "Search" %>
<% end %>
The RansackDemo page is a good place to play around with the different search options. There is a Simple Mode and an Advanced Mode. The source code is available on github and the views there give some indication of how to put together the groupings and conditions.
Additional info is also available in RailsCast 370.

throw this under your search_form_for tag. This is assuming that you're using f:
<%= f.combinator_select %>
it'll generate a select with two options. ALL or ANY. ANY will use an OR clause. ALL will use an AND clause.

Related

Form_for with render list of check_box

I have functionality search above tags. I want to render all tags with check_box in form_for that I will filter those tags and render all items again with new parameters.
= form_for #tags do |f|
- #tags.each do |tag|
f.check_box(#{tag}, "yes")
f.label_tag "#{tag}"
f.submit 'Filter'
end
I don't know what you are asking because your question is not much clear, but trying to understand your question. If I understood your question then you need to add a filter with tags on the search page, right? If yes then try the following steps.
Create a form for search tag like
<%= form_tag search_path, method: :get do %>
<% for tag in Model.order("name") %> #=> Model means which stored your tags like "Tag"
<%= check_box_tag("#{tag.name}[]", "#{tag.name}") %> tag.name
OR
<%= check_box_tag("tags[]", "#{tag.name}") %> tag.name
<% end %>
<%= submit_tag "Filter" %>
<% end %>
Or If you need filter separately clicking link and keep current search then
<% for tag in Model.order("name") %> #=> Model means which stored your tags like "Tag"
<%= link_to tag.name, request.query_parameters.merge({tag: tag.name}) %>
<% end %>
See the below image for keep current search and filter by clicking on the link
These all are view functionality, you need to update your SQL query.
I think it will help.
It's work:
= form_tag({controller: 'searches', action: 'filter'}, method: 'get') do
ul
- #tags.each do |tag|
li
input type='checkbox' name="tags[]" checked="checked" id="#{tag}" value="#{tag}"
label_tag for="#{tag}" #{tag}
button Filter

Narrowing search with ransack

I've got workers, workers has many posts. I want to be able to search for a worker, displaying all his posts, then narrow down to the date the posts where made. I can search by name of the worker but when I try to search for date aswell it just displays all posts for that worker (if the date exists in one post).
what I'm trying to run with:
controller:
#q = Worker.ransack(params[:q])
#workers = #q.result.order(name: :asc).includes(:posts).uniq
view:
<%= search_form_for #q do |f| %>
<%= f.label :name_cont %>
<%= f.search_field :name_cont %>
<%= f.label :posts_date_start %>
<%= f.search_field :posts_date_start %>
<%= f.submit %>
<% end %>
<% #workers.each do |worker| %>
<% worker.posts.group_by { |t| t.date.to_time.beginning_of_month }.each do |month, posts| %>
<some table header logic>
<% posts.each do |post| %>
<table content>
Unless you created a custom predicate of start, that will not work.
From your group_by statement I can see that your posts has a date field. If you wanted posts only for the date specified you would use the eq predicate
<%= f.search_field :posts_date_eq %>
If you need to massage your user input, I would look into making a custom predicate you can look at how to do that here -> creating custom predicates
EDIT
To test parsing your date field string into a date put
begin
params[:q][:posts_date_eq] = Date.parse(params[:q][:posts_date_eq])
rescue
# no param present
end
before your search object
#q = Worker.ransack(params[:q])
I solved it like this
instead of
<% worker.posts.group_by { |t| t.date.to_time.beginning_of_month }.each do |month, posts| %>
I did
<% Post.search_post(params[:search_post]).search_post_present(params[:search_post_present]).where(worker_id: worker.id).order(date: :asc).group_by { |t| t.date.to_time.beginning_of_month }.each do |month, posts| %>
that pointed to a search hepler in post.rb
def self.search_post(search_post)
if search_post
where('date LIKE ?', "%#{search_post}%")
else
all
end
end
I then overlapped the forms for both ransack and this search, so both are run with the same submit button, and that worked just fine.

Display title instead of id from search results

I have spent hours on this single problem, I am desperate for help.
The below html displays the correct car name and the car.manufacture_id displays the correct manufacture id, except I need to display manufacture.name and can not figure out how to do that. How do I display car.manufacture.name?
search.html.erb
<% #cars.each do |car| %>
<%= car.manufacture_id %>
<%= link_to car.name, manufacture_path(car.manufacture_id) %>
<% end %>
search_controller.rb
def search
if params[:q].nil?
#cars = []
#manufactures = []
else
#cars = Car.search params[:q]
#manufactures = Manufacture.search params[:q]
end
end
What do your car and manufacture models looks like, can you show the code for them? The schemas would help too. If your models are setup right car.manufacture.name should have worked.
If you do
<% #manufactures.each do |manufacture| %>
<%= manufacture.id %>
<%= manufacture.name %>
<% end %>
Does this work?
Also this might work, if the manufacturers are being found by Manufacture.search params[:q]
<%= #manufactures.find(car.manufacture_id).name %>
or if they are not
<%= Manufacture.find(car.manufacture_id).name %>

Rails filtering row by column using select dropdown

I was making a travel vacation application. Searching of places is based on categories from select dropdown.
But I am not able to understand the program logic. I am able to load the content in the database. but can't filter based on certain categories.
I made a scaffold called listing and included certain parameters.
In the database it has a row of 5 columns, namely, place, description, image_url, price, category.
Now, if I create another controller, search, I am not able to load a row based on a category from the select dropdown.
Search_controller.rb
def index
#categories = Listing.find_by_sql("SELECT category FROM listings GROUP BY category").map &:category
#list = params[:category].blank? ? Listing.all : Listing.find_all_by_category(params[:category])
end
index.html.erb
<% form_tag(:action => :index) do %>
<%= select_tag "category", options_for_select(#categories) %>
<%= submit_tag "Filter" %>
<% end %>
<table>
<% #list.each do |list| %>
<tr>
<td><%= list.place %></td>
</tr>
<% end %>
</table>
It does not show the select option.
Also, I tried to do this without select form
Search_controller.rb
def index
#list = Listing.select(:category).map(&:category).uniq
end
Index.html.erb
<% #list.each do |r| %>
<%= r.place %>
<% end %>
It says: undefined method `place' for "sunny":String (where "sunny" is a category)
Basically, how do you get the row based on a certain column value. And, will the logic also apply to two select dropdowns?
I know I am close, but somethings not right. Please assist me.
Thanks a lot.
You are missing = before form_tag. Should be:
<%= form_tag(:action => :index) do %>
<%= select_tag "category", options_for_select(#categories) %>
<%= submit_tag "Filter" %>
<% end %>

Rails: Update only when checkbox is checked

I want to update a model - only lines where the checkox is clicked and insert a remark
View:
<%= form_tag update_fb_instruction_users_path, :method => :put do %>
<% #user_wishes.each do |u| %>
<%= u.user.name %>
<%= fields_for "instruction[]", u do |f| %>
<%= f.text_field :remark_tl %>
<% end %>
<%= check_box_tag "instruction_user_ids[]", u.id %>
<% end %>
Controller:
def update_fb
params[:instruction_user_ids].each do
#check = InstructionUser.update(params[:instruction].keys, params[:instruction].values).reject { |p| p.errors.empty? }
end
The issue there is that they all have the same name. So whatever value the last one is, that's what it will be in the request params.
It's a bit old, but you might want to check out the railscast here: http://railscasts.com/episodes/73-complex-forms-part-1. The basic idea is to use fields_for on top of each user object. I haven't done it myself before, otherwise i'd write a full solution :).

Resources