Filtering in Ruby on Rails - ruby-on-rails

I have an Ruby on Rails application in which I have the following resources pets, pet types, vaccinations(the event of vaccinating a pet) and persons. So, pet belongs to a type (a type has many pets) and vaccination belongs to a pet (a pet can have many vaccinations). What I want to do is the following: To have a collapsable list (a select) o all the pet types with a submit button in the vaccinations index, so that I can filter vaccinations by pet types. My code is the following:
This is the index method in the vaccination controler:
def index
if params[:type_id]
flash[:notice] = "Post successfully created"
#vaccinations = Vaccination.filter(params[:type_id])
else
#vaccinations = Vaccination.all
end
end
This is the search form in the vaccinations index:
<form action="/vaccinations" method="GET">
<%= #type_id %>
<select name="type_id">
<option disabled selected value> Select a classification </option>
<% Type.all.each_with_index do | t, index | %>
<option value="<%= t.id %>" <% t.id.to_s == #type_id ? "selected" : "" %>> <%= t.name%> </option>
<% end -%>
</select>
<input type="submit", value="SUBMIT" />
</form>
And this is my filter method in the vaccination model, the one that I call in the controller.
def self.filter(type_id)
t = Array.new
for v in Vaccination.all
if type_id == v.pet.type.id
t.push(v)
end
end
t
end
What happens is that when I don´t select any pet type, I can see every vaccination as it should be. But when I select any pet type, no matter the type of the pets that have been through a vaccination, it doesn´t show me anything. If i have made three vaccinations to cats an select cat, and filter, it shows me nothing as if I didn´t have any vaccinations. That´s my problem. Sorry for my english, it´s not my first language!

The correct way of doing it is through relationships.
Example ( should work fine, didn't test it ):
def self.filter(type_id)
Vaccination.joins(pet: :pet_type).where(
pet_types: {
id: type_id
}
)
end
Now you will get a list of vaccinations of all the pets with the sent type.

Related

Getting {", value= "=>"on"} as a paramater when I want an Object's id

I have a program that is supposed to simulate a delivery POS. A Delivery Object belongs_to a Meal Object, which has_many items. The form renders a bunch of items with a checkbox next to each item using helper methods like this...
#inside the app/models/item.rb file
def self.meal_field_maker(foods)
rStr = ""
foods.each do | sel |
rStr += "<p><input type= 'checkbox' name= 'meal[items][], value= '#{sel.id}'> #{sel.show} </p>"
end
return rStr
end
#inside the app/helpers/application_helper.rb file
def the_new_meal_form
foodgroups = Item.get_foodgroups #Gets each food group
rStr = ""
foodgroups.each do | sel |
rStr+= "\n<h3>#{sel}</h3>" #Adds the name of each Food Group as a header before checkboxes
groupedFoods = Item.list_items_of_group(sel) #Gets every item of a food group
rStr += Item.meal_field_maker(groupedFoods) #makes a checkbox input tag for each item in groupedFoods
end
return (rStr)
end
And this all renders properly in the form which looks like this...
<form method= "post" action= "new_user_delivery">
<input type= "hidden" name= "delivery[user]" value= <%= #user.id %>
<%= user_delivery_address_field(session).html_safe %>
<p>(Optional) Meal Name: <input type= "text" name="delivery[meal][name]"></p>
<p>----------------------------------------------------</p>
<%= the_new_meal_form.html_safe %>
<p>----------------------------------------------------</p>
<p>Proceed to Payment <input type= "submit" value= "Proceed">
</form>
And It looks like it all works perfectly, but on the next action the params look like this...
<ActionController::Parameters {"delivery"=>{"user"=>"11", "address"=>"98 Linden Ave", "meal"=>{"name"=>"FirstMeal"}}, "meal"=>{"items"=>[{", value= "=>"on"}, {", value= "=>"on"}, {", value= "=>"on"}, {", value= "=>"on"}, {", value= "=>"on"}]}, "controller"=>"deliveries", "action"=>"payment_options", "id"=>"11"} permitted: false>
The issue here is clearly that for every item I select, I just get {", value= "=>"on"}, which of course gives me no indication which Item Objects were chose, as you see this is ~supposed~ to return the Item's ID as the parameter value. How do I fix this?
Your line here:
rStr += "<p><input type= 'checkbox' name= 'meal[items][], value= '#{sel.id}'> #{sel.show} </p>"
is missing a single quote after 'meal[items][]. Also make sure you don't have spaces immediately after equals signs:
rStr += "<p><input type='checkbox' name='meal[items][]', value='#{sel.id}'> #{sel.show} </p>"
I would say that it's generally a code smell if you have HTML building code inside your model. It's usually better to keep those in views or helpers, but that's outside the scope of this question.

Dynamic Category and Subcategory Selector [Rails 6] [duplicate]

This question already has answers here:
Rails 4 - dynamically populate 2nd select menu based on choice in first select menu in a nested form
(2 answers)
Closed 2 years ago.
I want to create a Category Select tag that when you select the category, changes the select options for another select_tag with the subcategories that belongs to the category selected.
I tried stimulus reflex, but i'm not happy with the result, other ways to do it?
It's for the _form.html.erb for the Project model, how do i do it without refreshing the page?
Pass your categories including their subcategories with it
#categories = Category.includes(:subcategories)
Then iterate over it on the first selector.
<select id="category" name="category_id">
<% #categories.each do |category| %>
<option value="<%= category.id %>"><%= category.name %></option>
<% end %>
</select>
<select id="subcategory" name="subcategory_id" disabled></select>
Use javascript on the second selector to generate his elements dynamically based on first input value. Place a listener on the first, to track when it's value changes.
<script>
var categories = <%= #categories %>
$("#category").change(function(e) {
var subcategories = [];
var selectedCategoryId = $(this).val();
$('#subcategory').empty();
subcategories = categories.find(x => x.id === selectedCategoryId).subcategories;
subcategories.each(function (sub) {
$('#subcategory').appendChild(`<option value="${sub.id}">${sub.name}</option>`);
});
$('#subcategory').prop('disabled', false);
});
</script>
This would work. You could also create a helper and call it by an ajax as well.

How to use sort_by or order_by on view and controller with will_paginate?

In my rails application I am limiting the amount of rooms displayed on a page through pagination, I want to allow the user to order/sort the results to different columns of the room model. I think I will need a drop down menu to do this, and then pass this data over to my rooms_controller maybe through an instance variable.
How can I sort the rooms with the select tag according to a column and what do I need to do in the corresponding controller to make this work?
At the moment I am using this for a drop down menu:
index.html.erb
...
...
<%= will_paginate #rooms %>
<div id="order-by">
<select>
<option value="asc">Distance</option>
<option value="asc">Name</option>
<option value="asc">Price (low to high)</option>
<option value="des">Price (high to low)</option>
<option value="asc">Reviews</option>
</select>
</div>
rooms_controller.rb
...
...
def index
#rooms = Room.paginate :page => params[:page], :per_page => 12
end
...
My room model has listing_name:string, address: string, nightly_price:integer and has_many reviews. My review model belongs_to room. I am using geocoder gem for the location of an room.
I have searched allot and tried multiple things to make this work and I can not figure this one out. For any hints on how to solve this I would be really happy!
If you need further information just let me know.
Something like:
index.html.erb
<%= will_paginate #rooms %>
<div id="order-by">
<form>
<select name="sort">
<option value="distance">Distance</option>
<option value="name">Name</option>
<option value="price">Price (low to high)</option>
<option value="price desc">Price (high to low)</option>
<option value="review">Reviews</option>
</select>
<input type="submit" value="Sort"/>
</form>
</div>
rooms_controller.rb
def index
#rooms = Room.order(params[:sort]).paginate(page: params[:page], per_page: 12)
end
Also need to ensure that params[:sort] is included into only available values,
e.g.:
sort = params[:sort]
sort = nil unless sort.in?(['distance', 'name', 'price', 'price desc', 'review'])
#rooms = Room.order(sort).paginate(page: params[:page], per_page: 12)
Consider to use separate scope for sorting or some gem. e.g. ransack

Saving select box options content instead of value

I have this lines in my form
<%= f.fields_for :attached_vehicles do |av| %>
<p>Select make</p>
<%= av.select :make, options_for_select(#makes.collect { |make|[make.make_name, make.id] }), { include_blank: "Select make" }, {} %>
...
<% end %>
which renders this in html
<select name="diy[attached_vehicles_attributes][0][make]" id="diy_attached_vehicles_attributes_0_make">
<option value="">Select make</option>
<option value="1">ACURA</option>
<option value="2">ALFA ROMEO</option>
<option value="3">AM GENERAL</option>
<option value="4">AMERICAN IRONHORSE</option>
<option value="5">AMERICAN LAFRANCE</option>
...
</select>
So now it saves the value of selected option to database, and i need it to save content of selected option.
Also I can't just replace make.id with make.make_name in "options_for_select", because I need value to be id so my other dynamic select box gets right options depending on selected option.
------------------------------------------------------------------------------------------------------------------------------------EDIT
So I did as Dharam suggested
...
def diy_params
params[:diy][:attached_vehicles_attributes].each_with_index do |make_id, index|
params[:diy][:attached_vehicles_attributes][index][:make] = Make.find(make_id).make_name
end
params.require(:diy).permit(:title, :summary, :tip, :warning, attached_vehicles_attributes: [:make, :model, :start_year, :end_year], steps_attributes: [:step_content, add_images_to_steps_attributes: [:image]])
end
...
And I keep getting this error
Couldn't find all Makes with 'id': (0, {"make"=>"12", "model"=>"XPEDITOR", "start_year"=>"2002", "end_year"=>"2010"}) (found 0 results, but was looking for 2)
So i have tried
...Make.find(make_id.first.make).make_name
and multiple other things but didn't get it working, what i'm doing wrong?
------------------------------------------------------------------------------------------------------------------------------------EDIT2
The value of make_id seems to be
(0, {"make"=>"12", "model"=>"XPEDITOR", "start_year"=>"2002", "end_year"=>"2010"})
because it tries to find Make with it as id.
And parameters in console looks like
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Kr4yvJUPCzUagUaW1glt69HEychEz+6QyHpGjKVKQ883rTUl0pZD+9SZSaQujHgM9k7jRt0vP1WTV5fMp8xyJw==", "diy"=>{"attached_vehicles_attributes"=>{"0"=>{"make"=>"12", "model"=>"XPEDITOR", "start_year"=>"2002", "end_year"=>"2010"}}, "title"=>"afaf", "summary"=>"AFSfAS", "tip"=>"FAF", "warning"=>"fdsgfsd", "steps_attributes"=>{"0"=>{"step_content"=>"gsdgsdg"}}}, "commit"=>"Create Diy"}
Before processing the params in your controller, you can do the following:
params[:diy][:attached_vehicles_attributes].each do |index, make_attributes|
params[:diy][:attached_vehicles_attributes][index]['make'] = Make.find(make_attributes['make']).name
end
You can replace Make model with the actual model that is backing the #models.

How to parse nested ul/li tags using Hpricot

I have the following HTML structure
<div id='my_categories'>
<ul>
<li>Animals, Birds, & Pets</li>
<li>Ask the Expert
<ul>
<li><a href='21'>Health Care Providers</a></li>
<li><a href='22'>Influnza</a>
<ul>
<li><a href='221'>Flu Viruses (2)</a></li>
<li><a href='222'>Test</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
This is how the web page looks
What I need is, I have a categories table with fields category_name, category_url and parent_id.
I need to save each category and sub-category. The parent_id denotes under which category does this sub-category comes under.
How can I parse through this HTML structure using this Hpricot and save data to my database. Please help
My table looks like
id category_name category_url Parent_id
1 Animals, Birds, & Pets null null
2 Ask the expert null null
3 Health Care Providers null 2
4 Influenza null 2
5 Flu Viruses null 4
6 Test null 4
Thanks in advance
Below is the code that worked for me...
doc = Hpricot(open(categories_page).read)
doc.search("ul/li").each do |li|
category = li.search('a[#href]').first.inner_text.gsub(/ *\(.*?\)/, '')
category_url = li.search('a').first[:href]
category = Category.find_or_create_by_name(category, :url => category_url)
puts "---------- #{category.name} ------------"
nodes = li.search("ul/li/a")
unless nodes.empty?
nodes.each do |node|
node_name = node.inner_text.gsub(/ *\(.*?\)/, '')
node_url = node.attributes['href']
sub_category = Category.find_by_name(node_name)
if sub_category.blank?
sub_category = Category.create(:name => node_name, :url => node_url, :parent_category_id => category.id)
puts " #{sub_category.name}"
else
sub_category.update_attribute('parent_category_id', category.id)
puts " #{category.name} --> #{sub_category.name}"
end
end
end
end

Resources