How can i update my lisbox using ajax? - ruby-on-rails

How can i create an ajax in my search when i select a country it would show me all states that i have in the country selected
I'm trying to create a display when i select country automatically show all the states that has the country selected
My tables
Countries
|id| |country_name|
1 'USA'
2 'Peru'
States
|id| |state_name|
1 Alabama
2 Machupicchu
Country_States
|id| |country_id| |state_id|
1 1 1
2 2 2
My controller
class Country_StatesController < ApplicationController
def conditional
#countries = Country.find(:all)
#states= State.find(:all)
#selected_country = Country.find_by_id(params[:countries]) if params[:countries].to_i
#selected_state = State.find_by_id(params[:states]) if params[:states].to_i
#search= CountryState.find(:all,:conditions=> ['state_id','country_id' ],params[:states],params[:countries] )
end
end
My view
<% form_tag :controller=>"country_States",:action=>"conditional" do %>
<%= select_tag "countries", options_for_select(#countries.collect {|t| [t.state_name.to_s ,t.id]}) %>
<%= select_tag "states", options_for_select(#states.collect {|t| [t.state_name.to_s ,t.id]}, params[:search].to_i ) %>
<%= submit_tag "Search", :name => nil %>
<% end %>
I found something like this
<%= collection_select :selection, :level, User::LEVELS, :to_s, :to_s, {},
{:onchange => remote_function(
:url => {:action => "updatelevel", :controller => "user", :id=> user.id},
:with => "'level_id='+this.value"
)
}
%>
I will appreciate help.

To list all the states belonging to a given country first set up the following relationship:
class Country < ActiveRecord::Base
has_many :states
end
class State < ActiveRecord::Base
belongs_to :country
end
Then in the controller you can call all states like this:
#country = Country.find(params[:id])
#states = #country.states #this will be a hash of all states that belong_to #country
and in the view, you can create a list like this (or use a table, depending on how you want it to be formatted):
<ul>
<% #states.each do |state| %>
<li>
<%= state.name %>
</li>
#etc
<% end %>
</ul>

I found a very simple answer here:
http://pullmonkey.com/2008/03/30/dynamic-select-boxes-ruby-on-rails/
Is very useful and descriptive.

Related

Custom searching a belongs_to assocation is empty

sorry it may be simple but it's making me bash my head against a wall!
I created my own searches model and controller and having trouble searching a belongs_to association. I am able to search for has_and_belongs_to_many associations fine but I get zero results for belong_to.
# models/user.rb
class User < ApplicationRecord
belongs_to :city
has_and_belongs_to_many :sports
has_and_belongs_to_many :goals
end
# models/search.rb
class Search < ApplicationRecord
def search_users
users = User.all
# These two work
users = users.joins(:sports).where("sports.name ILIKE ?", "%#{sports}%") if sports.present?
users = users.joins(:goals).where("goals.name ILIKE ?", "%#{goals}%") if goals.present?
# This doesn't
users = users.joins(:city).where("cities.name ILIKE ?", "%#{cities}") if cities.present?
return users
end
end
# searches_controller.rb
class SearchesController < ApplicationController
def new
#search = Search.new
#sports = Sport.uniq.pluck(:name)
#goals = Goal.uniq.pluck(:name)
#cities = City.uniq.pluck(:name)
end
def create
#search = Search.create(search_params)
redirect_to #search
end
def show
#search = Search.find(params[:id])
end
private
def search_params
params.require(:search).permit(:sports, :goals, :gyms, :cities)
end
end
and my views:
#searches/new.html.erb
<%= simple_form_for #search do |search| %>
<%= search.label :sports %>
<%= search.select :sports, options_for_select(#sports), include_blank: :true %>
<%= search.label :goals %>
<%= search.select :goals, options_for_select(#goals), include_blank: :true %>
<%= search.input :cities, collection: City.all.order(name: :asc), as: :select, label: "City" %>
<%= submit_tag "Search" %>
<% end %>
searches/show.html.erb
<% if #search.search_users.empty? %>
Nothing
<% else %>
<% #search.search_users.each do |user| %>
<%= user.first_name + ' ' + user.last_name %>
<% end %>
<% end %>
Basically when selecting a City from the dropdown list it doesn't register and gives me the empty search condition and I can't figure out why it won't select it. However selecting the sports and/or goals and it gives me the user matching those.
Thanks in advance!
EDIT:
Okay I've managed to get it working by simply changing my dropdown select in my view from:
<%= search.input :cities, collection: City.all.order(name: :asc), as: :select, label: "City" %>
to this:
<%= search.select :cities, options_for_select(#cities) %>
HOWEVER, I'd still like to know why the other way doesn't work?
<%= search.input :cities, collection: City.all.order(name: :asc), as: :select, label: "City" %>
One of the reasons the above code didn't work is,
City.all.order(name: :asc) return a ActiveRecord::Relation object, but a collection searches for an array or range.
Collections can be arrays or ranges. from the collection documentation
Another point from that documentaion is,
when a :collection is given the :select input will be rendered by default, so we don't need to pass the as: :select
So, change the input to
<%= search.input :cities, collection: City.uniq.pluck(:name).sort,label: "City" %>

How can I rectify ActiveRecord::Associations::CollectionProxy

I am creating a category select dropdown to add categories to an event.
I can add them and they are showing in the form for the edit area, I can see the categories added in the backend.
When I try to show them in the views it gives me this strange error inside the layout:
<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Category:0x00000102542f10>
In my setup I have got this:
views/events/index.html.erb
<%=
event.categories.each do |events|
category.name
end
%>
models/category.rb
class Category < ActiveRecord::Base
belongs_to :event
belongs_to :profile
belongs_to :classified
belongs_to :page
extend FriendlyId
friendly_id :name, use: :slugged
end
admin/category.rb
ActiveAdmin.register Category do
controller do
def permitted_params
params.permit category: [:name, :description]
end
def find_resource
scoped_collection.friendly.find(params[:id])
end
end
form do |f|
f.inputs "Name" do
f.input :name
end
f.inputs "Description" do
f.input :description, :as => :ckeditor, :label => false, :input_html => { :ckeditor => { :toolbar => 'Full', :height => 400 } }
end
f.actions
end
end
In my categories table there is an event_id column in there so it can fnd the associated event and it links to both the events table and the categories table.
Any insight into this would be great
Thanks
Update views/events/index.html.erb as below:
<% if event.categories.count > 0 %>
<% event.categories.each do |category| %> ## Use <% %> to evaluate ruby code
<%= category.name %> ## Use <%= %> To evaluate and show the results
<% end %>
<% end %>
In your case, <%= %> will return event.categories value which is an instance of <ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Category which is what you see on the rendered page.
UPDATE
OP also had foreign_key concerns. Add foreign_keys for event, profile, classified and page in categories table.

Rails select tag using belongs_to association

I have the following models:
Product:
class Product < ActiveRecord::Base
belongs_to :user
...
end
User
class User < ActiveRecord::Base
has_many :products
end
In my products view I need a drop down list of users, and when a user is selected, it should be associated with that specific product.
This is my view:
<%= form_tag (update_user_products_path) do %>
<%#products.each do |product| %>
<div class = "prod">
<img src='<%= product.cover_img %>' class='product_image_prods'></img>
<div class= "title"><small><b><%= link_to truncate(product.title, :length =>30), recommendations_path(:product_id => product.id, :rating_set_id => params[:rating_set_id]), :target => '_blank' %></b></small></div>
<br/>
<div><em>Current Rating: <%= product.rating %> </em></div>
<%= hidden_field_tag :product_id, product.id %>
<%= select_tag "user_id", options_for_select(User.all.collect {|u| [ u.name, u.id ] })%>
</div>
<% end %>
<%= submit_tag %>
<% end %>
I am confused as to if I should use form_tag and updated the Product.user_id, or should use nested_attributes for the user model in my product from?
UPDATE:
Products Controller Action:
def update_user
#product = Product.find(params["product_id"])
#product.update_attribute(:user_id, params[:user_id])
redirect_to :back, :flash => { :notice => "Updated users" }
end
Also updated my view. How do I update all product records with the correct user_id. Currently, when I submit my from, it updates just 1 product record.
All you have to do is figure which user was associated with which product.
For example (hooking the tag with product.id)
<%= form_tag(update_user_path, :id => "update_user_form") do %>
<%#products.each do |product| %>
<%= select_tag "user_id:#{product.id}", options_for_select(User.all.collect {|u| [ u.name, u.id ] })%>
<% end %>
<% end %>
When you submit you will get the the key with the product id and the selected user's id.
For example lets say product.id = 1 and user.id = 2
params will include
key => user_id:1 value=> 2
so taking the key and splitting it on : will give you the product_id then getting the value of that hash entry will give you the selected user.id for that product.

RoR voting system. How to count up votes, down votes, and total votes?

I am trying to create a voting system. The models that are being voted on are Issues and I have another model called Vote that holds an issue_id and a vote value of 0 or 1. The votes are being created with forms with hidden fields. This is on the issues index view.
<h1>Votes</h1>
<% #issues.each do |issue| %>
<li>
<div class="issue">
<h2><%= issue.title %></h2>
<p><%= issue.body %></p>
<%= form_for(#vote, :remote => true) do |f| %>
<%= f.hidden_field "issue_id", :value => issue.id %>
<%= f.hidden_field "vote", :value => 1 %>
<%= submit_tag "Up", :class => 'up-vote' %>
<% end %>
<%= form_for(#vote, :remote => true) do |f| %>
<%= f.hidden_field "issue_id", :value => issue.id %>
<%= f.hidden_field "vote", :value => 0 %>
<%= submit_tag "Down", :class => 'down-vote' %>
<% end %>
</div>
</li>
<% end %>
There is a has_many and belongs_to relationship between issues and votes. I want to display the number of up votes and down votes next to the buttons for each issue. So I need to pull all the votes with vote = 1 for each issue, as well as all the ones with vote = 0, and count each. Also want to know total votes. How should I do this? I have counter_cache set on the vote models issue association and votes_count column in my issues schema. Should this work be done in the controller or the model?
I haven't tried it myself, but you should try adding some methods to your Issue model like this:
def upvote_count
votes.count(:conditions => "value = 1")
end
def downvote_count
votes.count(:conditions => "value = 0")
end
I learned this in the Rails documentation. You can see for yourself here:
http://ar.rubyonrails.org/classes/ActiveRecord/Calculations/ClassMethods.html
http://apidock.com/rails/ActiveRecord/Associations/CollectionAssociation/count
ActiveRecord has a count method that should do what you want: http://api.rubyonrails.org/classes/ActiveRecord/Calculations.html#method-i-count
For example, in your controller:
#upvotes_count = Vote.count(:conditions => "issue_id = #{#issue.id} AND value = 1")
#downvotes_count = Vote.count(:conditions => "issue_id = #{#issue.id} AND value = 0")
#allvotes_count = Vote.count(:conditions => "issue_id = #{#issue.id}")
Do you really need to store votes by their own? If you don't have any other constraint, you'd do with two fields: upvotes and downvotes. Then you define two actions, "upvote" and "downvote" which update the corresponding field by 1. You can do it atomically, using something like
(model)
class Issue < AR::Base
def self.upvote(id)
self.where(:id => id).update_all("upvotes = upvotes + 1")
end
def self.downvote(id)
self.where(:id => id).update_all("downvotes = downvotes + 1")
end
end
(controller)
class IssuesController < ApplicationController
def upvote
Issue.upvote(params[:id])
end
def downvote
Issue.upvote(params[:id])
end
end
(router)
resources :issues do
member do
post :upvote
post :downvote
end
end
(view - haml)
= form_tag upvote_issue_path(#issue) do
= submit_tag "Up"
= form_tag downvote_issue_path(#issue) do
= submit_tag "Down"

Rails: filter index via dropdown and checkboxes

I'm trying to filter an index page of products via a dropdown menu (locations) and a set of checkboxes (categories) and not being very successful with it. I can filter via a dropdown for either location or category. I can also combine the two dropdowns within the one form but if I can't get a working solution to two separate forms.
What i'd like to achieve is a dropdown for location that submits onchange and the categories I'd like to have as checkboxes with a filter button.
The code I have at the moment provides the dropdown and checkboxes but there are some problems:
the checkboxes list all the categories but when I filter based on these the params are passed as an array but no products are returned in the view
whenever I filter by category i lose the previous location selection
Here's the relevant code:
Product Model
....
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :localizations
has_many :locations, :through => :localizations
class Product < ActiveRecord::Base
default_scope :order => 'end_date'
scope :not_expired, where('end_date > ?', Time.now)
scope :location, lambda { |*location_id| {:include => :locations, :conditions => ["locations.id = ?", location_id]} }
scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["categories.id = ?", category_id]} }
scope :unique, :group => "title"
Controller
class LibraryController < ApplicationController
def index
if params[:location_id] && params[:category_ids]
#products = Product.not_expired.unique.location(params[:location_id]).category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
elsif params[:category_ids]
#products = Product.not_expired.unique.category(params[:category_ids]).paginate(:page => params[:page], :per_page => 9)
elsif params[:location_id]
#products = Product.not_expired.unique.location(params[:location_id]).paginate(:page => params[:page], :per_page => 9)
else
#products = Product.not_expired.unique.paginate(:page => params[:page], :per_page => 9)
end
end
end
Library index.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<div class="filter_options">
<form class="filter_locations", method="get">
<% #options = Location.all.map { |a| [ a.name, a.id ] } %>
<%= select_tag "location_id", options_for_select(#options), :onchange => "this.form.submit();", :include_blank => true %>
</form>
<form class="filter_categories", method="get">
<% for category in Category.all %>
<%= check_box_tag("[category_ids][]", category.id) %>
<%= category.name %>
<% end %>
<input type="submit" value="Filter" />
</form>
</div>
I've been going around in circles with this so any direction is greatly appreciated.
to part answer my own question I've modified the library index and used a hidden field in the category form that calls for the location_id param, if it exists, which means I can retain any location selection that's been made after selecting category checkboxes.
Further update is I've added a check for whether the category checkbox is checked by querying the params, updated library index.html.erb below.
Last edit with #rdvdijk input incorporated (Thanks)
library index.html.erb
.......
<%= form_tag( '', :method => :get ) do %>
<% #options = Location.all.map { |a| [ a.name, a.id ] } %>
<%= select_tag "location_id", options_for_select((#options), params[:location_id]), :onchange => "this.form.submit();", :include_blank => true %>
<% end %>
<%= form_tag( '', :method => :get ) do %>
<% if(params.has_key?(:location_id)) %>
<%= hidden_field_tag 'location_id', params[:location_id] %>
<% end %>
<% Category.all.each do |category| %>
<%= check_box_tag 'category_ids[]', category.id, params[:category_ids].to_s.include?(category.id_to_s) %>
<%= category.name %>
<% end %>
<%= submit_tag 'Filter' %>
<% end %>
.......
You have two forms, I think that is part of your problem. Whenever you change a location in the first form, only the location_id will be sent to your controller index action. Whenever your select a category and submit the second form, only the category_ids will be sent to your controller index action.
Use one form and see what happens. It should at least make the filtering work for a single submit.
The second problem I see is that you don't select the chosen location, or check the chosen categories.
Take a look at the documentation for options_for_select and check_box_tag to fix that.
In my case, product belongs_to :category and category has_many :products, I modified categories.id to category_id, it works!
scope :category, lambda { |*category_id| {:include => :categories, :conditions => ["category_id = ?", category_id]} }

Resources