I'm very new to rails and have this fairly basic question:
I have a form that takes in an array:
<td><%= fields_for "days" do |form| %>
M: <%= form.check_box "", {}, 'M', '' %>
T: <%= form.check_box "", {}, 'T', '' %>
W: <%= form.check_box "", {}, 'W', '' %>
Th: <%= form.check_box "", {}, 'Th', '' %>
F: <%= form.check_box "", {}, 'F', '' %>
<% end %>
This should be accessible through params[:days]. How can I assign params[:days] to a variable within the controller? #days is not correct here, right? (There's no Days object, so there's no instance of that object). What should go in the [correct_variable] slot below?
[correct_variable] = params[:days]
Thanks!
In response to comments:
I tried using #days, but for some reason it wouldn't get called where I'd like it to. In particular, I'd like to pass it to my Search model:
class Search < ActiveRecord::Base
attr_accessible :name, :day, :units, :instructor
def courses
#courses ||= find_courses
end
private
def find_courses
Course.find(:all, :conditions => conditions)
end
def day_conditions
["courses.day LIKE ?", "%"+ #days.join("%")+"%"]
end
I first instantiate #days in my courses controller (which is connected, through the index method, to a partial that uses an instance of the Search object.
More code:
From courses/index.html.erb:
<% if #search.save %>
<div id = "results_scroll">
<%= render :partial => 'searches/search_results' %>
</div>
<% else %>
From search_results partial:
<% "Search" %>
<table>
<tr>
<th align="left" width="25%"><%= 'Name' %></th>
<th align="left" width="10%"><%= 'Number' %></th>
<th align="left" width="20%"><%= 'Instructor' %></th>
<th align="left" width="10%"><%= 'Room' %></th>
<th align="left" width="5%"><%= 'Day' %></th>
<th align="left" width="5%"><%= 'Units' %></th>
<th align="left" width="15%"><%= 'Time' %></th>
<th align="left" width="10%"><%= 'Limitations' %></th>
</tr>
<%= render :partial => #search_show.courses %>
</table>
From the courses controller (this has the #search_show variable).
def index
#courses = Course.order(sort_column + " " + sort_direction)
#search = Search.new
#search_show = Search.last
#title = "List"
#days = params[:days]
Finally, the _course.html.erb partial:
<tr>
<td><%= course.name %></td>
<td><%= course.number %></td>
<td><%= course.instructor %></td>
<td><%= course.room %></td>
<td><%= course.day %></td>
<td><%= course.units %></td>
<td><%= course.time %></td>
<td><%= course.limitations %></td>
<td><%= link_to 'Show', course %></td>
</tr>
This is not really an answer, but there is some problems with how you are trying to access your #days variable you set in the controller.
# your controller
...
def index
...
#days = params[:days]
# your model
...
private
def day_conditions
["courses.day LIKE ?", "%"+ #days.join("%")+"%"]
end
The #days, in your model, you are calling is not going to access the #days in your controller. Each #days belongs to their respective instances.
You should find a method of sending the #days from your controller into your models, instead of using global variables.
Solved the problem by using a $days global variable instead of #days.
Related
I am trying to list the product reviews in spree back end. But getting the error 'undefined method any '. I am new to ruby,please help me to solve this issue.
Thanks in Advance.
Index.html.erb:
<% if #reviews.any? %>
<table class="index">
<colgroup>
<col style="width: 25%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 20%;">
<col style="width: 15%;">
<col style="width: 17%;">
</colgroup>
<thead>
<tr>
<th><%= Spree.t('product') %></th>
<th><%= Spree::Review.human_attribute_name(:rating) %></th>
<th><%= Spree.t('feedback') %></th>
<th><%= Spree::Review.human_attribute_name(:user) %></th>
<th><%= Spree::Review.human_attribute_name(:created_at) %></th>
</tr>
</thead>
<tbody>
<%- #reviews.each do |review| -%>
<tr id="<%= dom_id review %>">
<td>
<% if review.product %>
<%= link_to review.product.name, product_path(review.product) %>
<% end %>
</td>
<td class="align-center">
<%= txt_stars(review.rating) %>
</td>
<td class="align-center">
<%= link_to "(#{review.feedback_stars}/#{review.feedback_reviews.size})", admin_review_feedback_reviews_path(review) %>
</td>
<td class="align-center">
<%= review.user_id ? link_to(review.user.try(:email), [:admin, review.user]) : Spree.t(:anonymous) %></p>
<p><%= Spree::Review.human_attribute_name(:ip_address) %>: <%= review.ip_address ? link_to(review.ip_address, "http://whois.domaintools.com/#{review.ip_address}") : '-' %></p>
</td>
<td class="align-center">
<%= l review.created_at, :format => :short %>
</td>
<td class="actions">
<%= link_to_with_icon 'check', Spree.t('approve'), approve_admin_review_url(review), :no_text => true, class: 'approve' unless review.approved %>
<%= link_to_edit review, :no_text => true, :class => 'edit' %>
<%= link_to_delete review, :no_text => true %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div class="no-objects-found">
<%= Spree.t(:no_results) %>
</div>
<% end %>
The above shown is the index.html.erb file , where the listing and ransack search is done.
Model File : review.rb
class Spree::Review < ActiveRecord::Base
belongs_to :product, touch: true
belongs_to :user, :class_name => Spree.user_class.to_s
has_many :feedback_reviews
after_save :recalculate_product_rating, :if => :approved?
after_destroy :recalculate_product_rating
validates :name, presence: true
validates :review, presence: true
validates :rating, numericality: { only_integer: true,
greater_than_or_equal_to: 1,
less_than_or_equal_to: 5,
message: Spree.t('you_must_enter_value_for_rating') }
default_scope { order("spree_reviews.created_at DESC") }
scope :localized, ->(lc) { where('spree_reviews.locale = ?', lc) }
scope :most_recent_first, -> { order('spree_reviews.created_at DESC') }
scope :oldest_first, -> { reorder('spree_reviews.created_at ASC') }
scope :preview, -> { limit(Spree::Reviews::Config[:preview_size]).oldest_first }
scope :approved, -> { where(approved: true) }
scope :not_approved, -> { where(approved: false) }
scope :default_approval_filter, -> { Spree::Reviews::Config[:include_unapproved_reviews] ? all : approved }
def feedback_stars
return 0 if feedback_reviews.size <= 0
((feedback_reviews.sum(:rating) / feedback_reviews.size) + 0.5).floor
end
def set_search
#search=Product.search(params[:q])
end
def recalculate_product_rating
self.product.recalculate_rating if product.present?
end
end
reviews_controller.rb
class Spree::Admin::ReviewsController < Spree::Admin::ResourceController
helper Spree::ReviewsHelper
def index
#reviews = collection
end
def approve
r = Spree::Review.find(params[:id])
if r.update_attribute(:approved, true)
flash[:notice] = Spree.t("info_approve_review")
else
flash[:error] = Spree.t("error_approve_review")
end
redirect_to admin_reviews_path
end
def edit
if #review.product.nil?
flash[:error] = Spree.t("error_no_product")
redirect_to admin_reviews_path and return
end
end
private
def collection
params[:q] ||= {}
#search = Spree::Review.ransack(params[:q])
#collection = #search.result.includes([:product, :user, :feedback_reviews]).page(params[:page]).per(params[:per_page])
end
end
It looks like the important code is in your comment on an answer, where it is very difficult to read.
I think you have assigned the variable collection with an integer id, and assigned the result if the database lookup to #collection (which is a different variable)
So to fix it you could change the index action to
#reviews = #collection
any works with array on and your #reviews are not an array. Please check #reviews object. It should be array.
I would like to create sortable columns for my table which tabulates data based on hashes. By following http://railscasts.com/episodes/228-sortable-table-columns?view=asciicast. From what I understand, order method would only work sorting out a Model. What's the best way of sorting out columns for such tables. I have 29 similar tables as mentioned. My codes are as below :-
admins_controller.rb
class AdminsController < ApplicationController
array =[]
User.each do |user|
company_name = Company.find(user.company_id).name
array.push(company_name)
end
company = array.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
end
Results of the above the above query would look like this :-
array = [["3M", 4], ["A.P. Møller-Mærsk Group", 10], ["ABB", 14], ["Abbott Laboratories", 12]]
On views :-
admins.html.erb
<table class="table">
<tr>
<th><%= link_to "Company", remote: true, :sort => "hash" %></th>
<th><%= link_to "Value", remote: true, :sort => "key" %></th>
<th><%= link_to "Percentage", remote: true, :sort => "Percentage" %></th>
</tr>
<% if #mentors.try(:any?) %>
<% #mentors.each do |key, value| %>
<tr>
<td><%= key %></td>
<td><%= value %> </td>
<td><%= ((value.to_f/#total_co.to_f).to_f * 100 ).round(2)%> </td>
</tr>
<% end %>
<% else %>
<td> nil </td>
<td> nil </td>
<td> nil </td>
<% end %>
</table>
You could go for a JavaScript / jQuery solution like http://tablesorter.com/docs/
This would allow for sorting in frontend and you would not need to adjust the backend.
If you want to have a backend solution, you could go for sorting by column index. A simple solution would be something like this:
Controller:
class AdminsController < ApplicationController
def index
array =[]
User.each do |user|
company_name = Company.find(user.company_id).name
array.push(company_name)
end
company = array.inject(Hash.new(0)) { |h, e| h[e] += 1 ; h }
sort_column = params.fetch(:sort, 0).to_i
company.sort! { |a, b| a[sort_column] <=> b[sort_column] }
end
end
View:
<table class="table">
<tr>
<th><%= link_to "Company", remote: true, :sort => 0 %></th>
<th><%= link_to "Value", remote: true, :sort => 1 %></th>
<th><%= link_to "Percentage", remote: true, :sort => 1 %></th>
</tr>
<% if #mentors.try(:any?) %>
<% #mentors.each do |key, value| %>
<tr>
<td><%= key %></td>
<td><%= value %> </td>
<td><%= ((value.to_f/#total_co.to_f).to_f * 100 ).round(2)%> </td>
</tr>
<% end %>
<% else %>
<td> nil </td>
<td> nil </td>
<td> nil </td>
<% end %>
</table>
For reverting sort order, you would need to also pass a direction state and probably reverse order.
Here is my code.
Controller:
def bisac_main_counts
q = "
MATCH (b:Bisac) WHERE (b.bisac_code =~ '.*000000')
WITH b, size((b)<-[:INCLUDED_IN]-()) as wokas_count
RETURN b.bisac_code as bisac_code, b.bisac_value as bisac_value, wokas_count
ORDER BY b.bisac_code
;"
#result = Neo4j::Session.current.query(q).to_a
if params[:limit]
#result = Kaminari.paginate_array(#result).page(params[:page]).per(params[:limit])
else
#result = Kaminari.paginate_array(#result).page(params[:page])
end
end
View:
<%= render 'home/main_links' %>
<%= paginate #result %>
<%= render 'bisac_counts' %>
<%= form_tag bisac_main_counts_path, method: :get do %>
<%= select_tag :limit, options_for_select([5, 10, 15, 20, 25], selected: params[:limit] || 25) %>
<% end %>
Partial:
<table>
<thead>
<tr>
<th>Bisac Code</th>
<th>Bisac Value</th>
<th>Wokas Count</th>
</tr>
</thead>
<tbody>
<% #result.each do |record| %>
<tr>
<td><%= record.bisac_code %></td>
<td><%= record.bisac_value%></td>
<td><%= record.wokas_count %></td>
</tr>
<% end %>
</tbody>
</table>
Apparently params[:limit] is not set in the view. It is always null. Changing pages is working.
What I am doing wrong here?
What was missing was a form for changing the limit and a way to trigger it.
Here are the changes (in the view only):
<%= render 'home/main_links' %>
<%= paginate #result %>
<%= render 'bisac_counts' %>
<%= form_tag bisac_main_counts_path, method: :get, id: 'limit_form' do %>
<%= select_tag :limit, options_for_select([5, 10, 15, 20, 25], selected: params[:limit] || 10) %>
<% end %>
<script type="text/javascript" >
$(function(){
$('#limit').change(
function() {
$('#limit_form').submit();
});
});
</script>
Controller
class GearsController < ApplicationController
before_action :set_gear, only: [:show, :edit, :update, :destroy]
def primary
#gears = Gear.search do
with(:Lab, 'Primary')
order_by(:RU, :desc)
end
end
Model
class Gear < ActiveRecord::Base
validates_uniqueness_of :Nic1mac, :Nic2mac, :Nic3mac, :IBmac, :SN, :allow_blank => true
attr_readonly :Devtype, :Nic1mac, :Nic2mac, :Nic3mac, :IBmac, :SN
scope :Mini, -> { where(lab: 'Mini') }
scope :Primary, -> { where(lab: 'Primary') }
scope :Support, -> { where(lab: 'Support') }
scope :M5, -> { where(lab: 'M5') }
scope :P5, -> { where(lab: 'P5') }
searchable do
integer :RU
text :Devname
text :Devtype
string :Lab
text :Swportib
text :Swport1
text :Swport2
text :Swport3
text :IBip
text :Nic1
text :Nic2
text :Nic3
text :Nic1mac
text :Nic2mac
text :Nic3mac
text :IBmac
text :Psu1
text :Psu2
text :SN
end
end
View
<% provide(:title, "SP4 Primary") %>
<p id="notice"><%= notice %></p>
<h1>SP4 Primary</h1>
<%= form_tag gears_path, :method => :get do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<head>
<style>
table, th, td { border: 1px solid black;}
th, td { padding: 15px;}
</style>
</head>
<table>
<thead>
<tr>
<th>RU</th>
<th>Dev Name</th>
<th>Dev Type</th>
<th>Lab</th>
<th>SW PortIB</th>
<th>SW Port1</th>
<th>SW Port2</th>
<th>SW Port3</th>
<th>IB IP</th>
<th>NIC1</th>
<th>NIC2</th>
<th>NIC3</th>
<th>NIC1 Mac</th>
<th>NIC2 Mac</th>
<th>NIC3 Mac</th>
<th>IB Mac</th>
<th>PSU1</th>
<th>PSU2</th>
<th>SN</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #gears.each do |gear| %>
<tr>
<td><%= gear.RU %></td>
<td><%= gear.Devname %></td>
<td><%= gear.Devtype %></td>
<td><%= gear.Lab %></td>
<td><%= gear.Swportib %></td>
<td><%= gear.Swport1 %></td>
<td><%= gear.Swport2 %></td>
<td><%= gear.Swport3 %></td>
<td><%= gear.IBip %></td>
<td><%= gear.Nic1 %></td>
<td><%= gear.Nic2 %></td>
<td><%= gear.Nic3 %></td>
<td><%= gear.Nic1mac %></td>
<td><%= gear.Nic2mac %></td>
<td><%= gear.Nic3mac %></td>
<td><%= gear.IBmac %></td>
<td><%= gear.Psu1 %></td>
<td><%= gear.Psu2 %></td>
<td><%= gear.SN %></td>
<td><%= link_to 'Show', gear %></td>
<td><%= link_to 'Edit', edit_gear_path(gear) %></td>
<td><%= link_to 'Destroy', gear, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
Above is my Controller and Model code. I am trying to set up the search so it only searches through records within the scope specified. Currently it will return all results and does not pay attention to the scope. I believe I am close to making it work but just don't have the right syntax. Then again I may be wrong, thus any help suggestions or different ways of doing this are welcome.
You can add a code like this in your search method
with(:lab, 'Support')
and in your model add this
string :lab
The solution was adding without in my gears_controller.rb file.
gears_controller.rb
def rack1
#gears = Gear.where("Lab like ? OR Lab like ? OR Lab like ?", "%Primary%", "%Mini%", "%Support%")
#search = Gear.search do
fulltext params[:search]
without(:Lab, "P5")
without(:Lab, "M5")
order_by(:RU, :desc)
end
#gears = #search.results
end
Adding the without fields allowed me to only search through the records with the specific Lab values that were specified in my #gears variable.
I am trying to use will_paginate for a list of items I want to display.
There is a form with drop down selections to fetch objects by status.
This is my controller
def list
#person = Person.find_by_id(session[:person_id])
params[:status] = params[:redirect_status] if params.has_key?('redirect_status')
#statuses = Peptide.statuses
#status = 'Not Ordered'
#status = params[:status] if params[:status] != nil || params[:status] == ''
#peptides = Peptide.find(:all, :conditions => ['status = ?', #status]).paginate(:per_page => 30, :page => params[:page])
if Peptide.count.zero?
flash[:notice] = "There are not any peptides entered"
redirect_to :action => 'new'
end#if zero
end
This is in the view
<form action="/peptide/create_spreadsheet_of_not_ordered" enctype="multipart/form-data" method="post">
<table class="sortable" cellpading="5" cellspacing="2" width="100">
<tr class= "header-line">
<th>SS</th>
<th>Status</th>
<th>Peptide</th>
<th>Gene</th>
<th>Submitter</th>
<th>Created</th>
<th>Updated</th>
<th>Sequence</th>
<th>Modification</th>
<th>Vendor</th>
</tr>
<% for #peptide in #peptides.reverse %>
<tr valign = "top" class= "<%= cycle('color_one', 'color_two') %>">
<!--an error here during development likely indicates that the people table has not be repopulated or
that no submitter primer is present for a primer-->
<td sorttable_customkey = 0 > <%=check_box_tag "box[]", #peptide.id %>
<td><%= #peptide.status%></td>
<td class><%= link_to #peptide.name, :action => :report, :id => #peptide.id %></td>
<td><%= gene_links(#peptide.genes) rescue 'Error'%></td>
<td><%= #peptide.submitter.name rescue "" %></td>
<td <%= sorttable_customkey_from_date(#peptide.created_at)%> >
<%= #peptide.created_at.strftime("%b %d %Y") rescue "Unknown"%>
</td>
<td <%= sorttable_customkey_from_date(#peptide.updated_at)%> >
<%= #peptide.updated_at.strftime("%b %d %Y") rescue "Unknown"%>
</td>
<td><%= #peptide.sequence%></td>
<td><%= #peptide.modifications%></td>
<td><%= #peptide.vendor%></td>
<%= buttons() %>
</tr>
<%end%>
<%= will_paginate #peptides %>
</table>
<br>
<%= submit_tag "Create Spreadsheet"%>
The default list is grouped by status ordered.
however when I select any other status and submit the form the pagination links take me back to the default status.
Please help me resolve this issue.
Thanks
Without seeing the view, it sounds like you need to add the current params as an argument to the links for the other statuses...
Update
Try adding the params to your status link:
<%= link_to #peptide.name, peptide_path(#peptide, params), :action => :report, :id => #peptide.id %>
The documentation is here.