Activeadmin where to place this variable code from my view - ruby-on-rails

I have created a nice little view but it has some code in it that I would normally place in a controller. I have tried making a controller for the model but Active Admin ignores it. I have tried a small controller do block inside the Active Admin resource file which just caused errors. Where can I place this so that the supply_company Active Admin controller can access it?
<% supply_company_id = SupplyCompany.find(params[:id])
#ccarray = CompanyScore.where(supply_company_id: supply_company_id).pluck(:score) %>
The below partial works fine (yes i know ugly) but I can seem to find the spot to place the logic for it to be rendered in ActiveAdmin.
render partial
/app/views/admin/_supply_company_ratings.html.erb
<%
supply_company_id = SupplyCompany.find(params[:id])
#ccarray = CompanyScore.where(supply_company_id: supply_company_id).pluck(:score) %>
<% #ccarrayaverage = (#ccarray.inject 0, :+) / #ccarray.count%>
<% #ccarraypercent = (#ccarrayaverage.to_f)/10*100 %>
<% #divpercent = #ccarraypercent.to_s %>
Average Score
<h1> <%= #ccarrayaverage %></h1>
Total Score
<h1> <%= #ccarray.inject 0, :+ %></h1>
Total Votes
<h1> <%= #ccarray.count %> </h1>
Percent
<h1> <%= #ccarraypercent %> </h1>
<div class="progress">
<div class="progress-bar progress-bar-custom" role="progressbar" aria-valuenow="<%=#divpercent%>"
aria-valuemin="0" aria-valuemax="100" style="width:<%=#divpercent%>%">
<%= #divpercent.to_s %>% Percent
</div>
</div>
Maybe because its in a sidebar its not reading the activeadmin controller block.
/app/admin/supply_company.rb
show title: :company_name do
attributes_table do
row :company_name
end
end
sidebar "Products", only: :show do
attributes_table_for supply_company do
# row rating_for SupplyCompany, "price"
row :company_name
row "Ratings" do
render 'supply_company_ratings'
end
row :products do |pt|
pt.products.collect {|c| link_to c.product_name.capitalize, admin_products_path + "\/" + c.id.to_s}.join(", ").html_safe
end
end
end

Putting the code into AA controller block is right idea.
controller do
def index
supply_company_id = SupplyCompany.find(params[:id]).id # note .id part - it makes sure you pass an id not the whole object in the query below
#ccarray = CompanyScore.where(supply_company_id: supply_company_id).pluck(:score)
end
end

Related

Rails - def search issue

OK, I'm very new to Rails, so please be patient :)
I'm not sure how to structure the def search in the page controller so that it returns back the correct results (right now the results are blank).
I'm adapting a course code to my project. The original course is showing how to search for room by address rather than through the drop down attribute selection. It was also ordering the results by distance rather than a price. Here is what I come up with for my project:
def search
# STEP 1
if params[:search].present? && params[:search].strip != ""
session[:loc_search] = params[:search]
end
# STEP 2
if session[:loc_search] && session[:loc_search] != ""
#rooms_type = Room.where(active: true).order(session[:loc_search], order: 'price')
else
#rooms_type = Room.where(active: true).all
end
# STEP 3
#search = #rooms_type.ransack(params[:q])
#rooms = #search.result
#arrRooms = #rooms.to_a
end
I'm pretty sure that there are several mistakes in the def search.. could someone help me to figure this out?
Here are my Room model attribute.
class CreateRooms < ActiveRecord
def change
create_table :rooms do |t|
t.string :type
t.timestamps
end
end
end
Search widget on the homepage is structured in the following way:
<%= form_tag search_path, method: :get do %>
<div class="row">
<div class="col-md-7">
<%= select_tag :type, options_for_select([['Single', 1], ['Double', 2]]), ,class: "form-control" %>
</div>
<div class="col-md-2">
<%= submit_tag "Search", class: "btn btn-normal btn-block" %>
</div>
</div>
<% end %>
The search page does the following:
<div class = "row">
<% #rooms.each do |room| %>
<div class = "col-md-4">
<div class = "panel panel-default">
<div class = "panel-heading preview">
<% image_tag room.cover_photo (:medium) %>
</div>
<div class = "panel-body">
<% link_to room.type, room %>
</div>
</div>
</div>
<% end %>
</div>
Thank you.
UPDATED code based on #crispychicken feedback - see the screenshots enter image description here
First Issue: The content of your model is wrong. It belongs into a migration. Also, the active and price attributes are missing. And I think the attribute type is protected. You should rename it to something like RoomType.
To create the migration:
rails g migration create_rooms room_type:string active:boolean price:integer
And then do rails db:migrate
Second Issue:
In your controller, change the code in your Step 2 to:
#rooms_type = Room.where(active: true, room_type: session[:loc_search]).order(:price)
And you have to change type to room_type everywhere in your files.

Rails 5 - Iterating over part of an array for the view

I currently use EasyAutoComplete for a search form. If you hit 'View All' it redirects to the same page but with params[:name] to show all cards.
I render this with:
<% #cards.in_groups_of(6, false).each do |group| %>
<div class='row'>
<% group.each do |card| %>
<div class='col-sm-2 col-md-2'>
<div class="wrapperImg">
<%= link_to image_tag(card.image_url, class: "img-responsive"), {:controller => "cards", :action => "show", :id => card.id }%>
</div>
</div>
<% end %>
</div>
</div>
<% end %>
However, if you look up a specific set of cards it's going to return a couple hundred (or more) of essentially the same card. I can identify these cards by a parameter(rarity)
I was originally going to try to modify it in the controller, but that is an issue because the 'def index' makes the EasyAutoComplete work
def index
wild_search = "%#{params[:name]}%"
#cards = Card.order(multiverse_id: :desc).limit(30)
# debugger
##cards = #cards.where("name like :name", name: wild_search).page(params[:page]) if params[:name]
#cards = #cards.where("name like :name OR setName like :name", name: wild_search).page(params[:page]) if params[:name]
end
Is there a way for me to do something like
cards = #cards.where('rarity IS NOT ?', 'Land') or something similar in the view, then modify my output from #cards.in_group_of to cards.in_group_of? Or is there a way to use the Controller to do this and use def search instead of def index?
Welcome any input.
Like this?
<% #cards.where.not(rarity: "Land").in_groups_of(6, false).each do |group| %>
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods/WhereChain.html

Rails retrieving all records in show controller

In my rails category show controller for categories I have it setup like this
def show
#categories = Category.find_by(params[:name])
end
But when I visit this controller it returns all records of products found in the category instead of single category.
Here is the code in my view controller for category
<div class="grid">
<% #categories.products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
What am i doing wrong here?
First of all, for security purposes, you should never trust the params hash to retrieve records. Rails will "make the data safe" if you use a hash as your arguments. Use this code below:
def show
#category = Category.find_by(name: params[:name])
end
Second, usually on a show page, you only want to retrieve one record and therefore the variable should be named as singular. I corrected that above.
Third, it helps if you use proper indenting when posting examples. It makes it easier for us to help you.
Fourth, the line below (I changed #categories to #category) is basically saying: "Now that I have this single category, find all the products associated with it in the products table and put them into the |product| variable for iteration"
<% #category.products.each do |product| %>
I'm not sure what you want to do with the category, but if you keep this line of code, it will always show you all the products. Maybe you only want to show the most recent 3, in which case you could do something like this:
In your controller:
def show
#category = Category.find_by(name: params[:name])
#recent_products = #category.products.order(created_at: :desc).limit(3)
end
In your view:
<div class="grid">
<% #recent_products.each do |product| %>
<%= link_to product_path(id: product.slug, category_name: product.category.name), class: "card" do %>
<div class="product-image">
<%= image_tag product.productpic.url if product.productpic? %>
</div>
<div class="product-text">
<h2 class="product-title"> <%= product.name %></h2>
<h3 class="product-price">£<%= product.price %></h3>
</div>
<% end %>
<% end %>
</div>
You can do this way
in your controller you can write this code
def show
#category = Category.find_by_name(params[:name])
end
and in your view it will work
<div class="grid">
<% #category.products.each do |product|%>
// place your code what you want to display
<% end %>
</div>
I hope it would help you and still if you have any concern please let me know.

How can I dynamically update search results based on form input in Rails?

I want site visitors to be able to view nearby shows within a radius that can be input via dropdown form. I have a view that displays nearby shows using the Geocoder gem:
<h3> Shows near <%= request.location.city %> </h3>
<%= form_for #nearby_shows.first do |f| %>
<p> Radius (in miles): <%= f.select(:radii, [10,20,30,40,50], {},
:style => "width:50px", :selected => f.object.radii, :onchange =>
"location.href = '#{shows_path}'") %> </p>
<% end %>
<ul class="users">
<% #nearby_shows.each do |nearby_show| %>
<li>
<%= link_to nearby_show.show_name, nearby_show %>
</li>
<% end %>
</ul>
Right now the selection doesn't affect anything, and the selection isn't remembered in the form when the page refreshes.
The model, show.rb contains:
attr_accessor :radii
And the shows controller contains:
def index
#shows = Show.all
#radii = 50
#nearby_venues = Venue.near("Boulder, CO",#radii,:select =>
"id").to_a
#nearby_shows = Show.where(show_venue: #nearby_venues)
end
In production, I'll be using request.location.city, but in development I'm just using "Boulder, CO" as an example.
How can I set #radii using the input select form? I am concerned that form_for will not permit me to change a variable for the list of entities #nearby_shows.
If you want a fast AJAX solution, here's what I would do
First, add an ID to your list so it's easy to manipulate
<ul id="my_id" class="users"></ul>
I really don't understand why you need that <%= form_for #nearby_shows.first %> for ? If I understand well, you just want to show a select, and update the list of nearby shows based on what the user selects ?
routes.rb
resource :shows do
get 'update_nearby', on: :collection, constraints: { format: 'js' }
end
# GET /shows/update_nearby, meant to be used only with AJAX
your_view.html.erb
<%= form_tag update_nearby_shows_path, remote: :true do |f| %>
<p> Radius (in miles): <%= select_tag(:radii, [10,20,30,40,50], {},
:style => "width:50px", :selected => #radii, :onchange =>
"location.href = '#{shows_path}'") %> </p>
<% end %>
<!-- On Submit, it will request a JS response
You can add some JS to submit the form everytime the select changes -->
Add some JS specific respone
your_controller.rb
def update_nearby
find_nearby_shows
end
private
def find_nearby_shows
#radii = params[:radii] ? params[:radii] : 50
#nearby_venues = Venue.near("Boulder, CO",#radii,:select =>
"id").to_a
#nearby_shows = Show.where(show_venue: #nearby_venues)
end
update_nearby.js.erb
<% if #nearby_shows %>
// Empty the list
var id = $("#my_id").empty()
<% #nearby_shows.each do %>
// Add one <li> per show
$("<li>", { 'html': "<%= escape_javascript(link_to(nearby_show.show_name, nearby_show)) %>"}).appendTo(id)
<% end %>
<% end %>
Bonus : you said you wanted to save the radius ? You can actually try to add it to the user session
def index
...
#radii = session[:saved_radii] ? session[:saved_radii] : DEFAULT_RADIUS
...
end
def update_nearby
find_nearby_shows
session[:saved_radii] = #radii
end
But if you really want to save it for the user, you should have a preferred_radii field in your User model

Can't link to objects belonging to a category

I have a method that groups all my book categories together
def self.categories_list
joins(:books).
select('categories.id, categories.name, count(*) AS books_count').
group('categories.id, categories.name').
order('books_count DESC')
end
I can then output them to my view like so
#bookcategories = Category.categories_list
What I want to do then is link to all the books belonging to say 'Computing' by clicking 'Computing' in the view
<% #bookcategories.each do |b| %>
<li><%= link_to b.name, category_path(b.name) %></li>
<% end %>
This should take me to my show action of my category controller
def show
#category = Category.where(:name => params[:name]).first
#categorisedbooks = #category.books #get me all books that have the category name
end
and the view for the show action
<div class="container">
<div class="row ">
<div class="span12">
<% #categorisedbooks.each do |c| %>
<%= image_tag c.avatar.url(:medium), :class=> "allBooksCover" %>
<% end %>
</div>
</div>
</div>
So when I click 'Computing' for example I get
undefined method `books' for nil:NilClass
and the params are being passed as
Parameters:{"id"=>"Computing"}
So, you need in your show action
#category = Category.where(:name => params[:id]).first
# etc

Resources