I made a search (filtering) form to filter my objects according to given values. There is a Company model and search will be according to its attributes. This is my index.html.erb:
<% provide(:title, 'All companies') %>
<h1>All companies</h1>
<%= form_tag companies_path, :method => 'get' do %>
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
<table class="pretty" border="1" cellpadding="10">
<tr>
<th><%= sortable "name" %></th>
<th><%= sortable "city" %></th>
<th><%= sortable "country" %></th>
<th><%= sortable "street_address" %></th>
<th><%= sortable "sector" %></th>
<th><%= sortable "telephone" %></th>
<th><%= sortable "fax" %></th>
<th>DELETE</th>
</tr>
<% for company in #companies %>
<tr class="<%= cycle('oddrow', 'evenrow') -%>">
<td><%= link_to company.name, company %></td>
<td><%= company.city %></td>
<td><%= company.country %></td>
<td><%= company.street_address %></td>
<td><%= company.sector %></td>
<td><%= company.telephone %></td>
<td><%= company.fax %></td>
<td><% if current_user.admin? %>
|| <%= link_to "delete", company, method: :delete,
data: { confirm: "You sure?" } %>
<% end %></td>
</tr>
<% end %>
</table>
<%= will_paginate #companies %>
This is my companies_controller.rb
helper_method :sort_column, :sort_direction
def index
#companies = Company.search(params[:search]).order(sort_column + ' ' + sort_direction).paginate(:per_page => 10, :page => params[:page])
end
This is my model company.rb
class Company < ActiveRecord::Base
attr_accessible :city, :country, :fax, :name, :reseller, :sector, :street_address, :telephone, :id
has_many :users , dependent: :destroy
def name_for_form
"#{name}"
end
def self.search(search)
if search
q = "%#{search}"
where('name LIKE ? OR city LIKE ? OR country LIKE ? OR street_address LIKE ? OR telephone LIKE ? OR fax LIKE ? OR sector LIKE ?',
q,q,q,q,q,q,q)
else
scoped
end
end
validates :city, presence: true
validates :country, presence: true
validates :fax, presence: true
validates :name, presence: true
validates :sector, presence: true
validates :street_address, presence: true
validates :telephone, presence: true
end
Lets assume I have 3 companies named kalahari, kalahari 2, and kalahari2. When I search kalahari, it founds only 1 company, kalahari. I mean it can't find kalahari in kalahari 2, or kalahari2. Only founds exact matches. When I search kala, it founds nothing. How can I fix that most simply? I am new to rails and don't want to mess a lot of things.
The simplest change that will get what you want is adding a wildcard to the end of your search query:
q = "%#{search}%"
The % matches anything when used with LIKE, so your code as currently written will match anything that ends with your input (so it would match a query of 'foo' to 'afoo', 'b_foo', and '1 3 5 x foo'), but without a matching wildcard on the end, it will not match things that contain the query but don't end with it (so 'foo' will not match 'foobar' or 'afoox').
I am grouping mileage entries by month in my Rails 3.2 application:
mileages_controller.rb
def index
#mileages = Mileage.find_all_by_user_id(current_user.id)
#mileages_months = Mileage.find_all_by_user_id(current_user.id).group_by { |t| t.created_at.beginning_of_month }
respond_to do |format|
format.html # index.html.erb
format.json { render json: #mileages }
end
end
index.html.erb
<% #mileages_months.sort.each do |month, mileages| %>
<h4><%= month.strftime('%B %Y') %></h4>
<p>Total miles <strong><%= mileages.miles.sum %></strong>.</p>
<table>
<tr>
<th>Name</th>
<th>Miles</th>
<th>Start</th>
<th>Destination</th>
<th></th>
</tr>
<% for mileage in mileages %>
<tr>
<td><%= mileage.name %></td>
<td><%= mileage.miles %></td>
<td><%= mileage.start %></td>
<td><%= mileage.end %></td>
<td><%= link_to 'Show', mileage %></td>
</tr>
<% end %>
</table>
<% end %>
As you can see, I am trying to sum the total miles in each month using <%= mileages.miles.sum %>. This won't work - but <%= mileages.first.miles %> correctly shows the first entry's miles for each month.
What is the correct way of totalling up the miles column for each month?
Well you can create a helper method(to keep this logic seperate from the view) in the mileage_helper as :
def sum_mileges(mileages)
mileages.map(&:miles).sum
end
and then calling it in the view as
<p>Total miles <strong><%= sum_mileges(mileages) %></strong>.</p>
OR
you can do it directly as :
<p>Total miles <strong><%= mileages.map(&:miles).sum %></strong>.</p>
I have an app which allows users to add recipes and then select their favourite recipes to view in their member area, I can select a favourite and i am getting the user_id, recipe_id and giving it a favourite_id.
What I would like to do is output the actual recipe to my view (as a favourite), like dish name, country_of_origin etc. I can do this with an actual recipe but not the favourite.Do i need to use has_many_through for this?
My models look like this
User
has_many :recipes
has_many :favourites
recipe
belongs_to :user
has_many :ingredients
has_many :preperations
has_many :favourites
favourites
belongs_to :user
belongs_to :recipe
attr_accessible :user_id, :recipe_id
My controller
#favourites = current_user.favourites
my link_to post
<%= link_to "Add to favorites", {:controller => 'favourites', :action => 'create', :recipe_id => r.id}, {:method => :post } %>
i can list the current users recipes, this is my contoller for this
#recipes = current_user.recipes if current_user.recipes
and then output them to the view like so
<% #recipes.each do |r| %>
<tr>
<td><%= r.dish_name %></td>
<td><%= r.country_of_origin %></td>
<td><%= r.difficulty %></td>
<td><%= r.preperation_time %></td>
<td><%= ingredient_names(r.ingredients) %></td>
<td><%= preperation_steps(r.preperations) %></td>
<td><%= image_tag r.avatar.url(:thumb)%></td>
<tr>
So if i do this in the view
<li><%= #favourites %></li>
I get this outputted
<Favourite id: 16, user_id: 8, recipe_id: 21, created_at: "2012-11-07 20:24:39", updated_at: "2012-11-07 20:24:39">]
If i try
<%= #favourites.dish_name %>
then i get the error undefined method dish_name
How do i get the params of the recipe model to show in the view. I do apologise just cant work it out, which should be really easy i guess?
Any help appreciated
You get undefined dish_name because your Favourite model does not have such attribute.
#favourites = current_user.favourites returns an array of Favourite objects.
In your view you would do something like
<% #favourites.each do |f| %>
<%= f.recipe %>
<% end %>
That will display all the recipes your current_user favorites. You could narrow it down to display a specific recipe or what not.
The favorites is just holding the relationship.
You can access the recipe by
#favourites.recipe
which will then be a recipe object and contain your attributes like dish_name etc.
#favourites is an array, yes? Then you must loop through #favourites and work with each element individually as so:
<% #favourites.each do |favorite| %>
<%= favorite.recipe.dish_name %>
<% end %>
I am working with a legacy database and am also reading through the Rails guides on associations.
I have two models. A diary model and an animal model.
diary.rb
class Diary < ActiveRecord::Base
establish_connection :premvet
attr_accessible :DiaryNo ,:DiaryName, :DiaryDate, :SlotHour, :TotalSlots, :BlockSlots, :BlockBooked, :FreeSlot, :BookedSlot
self.table_name = 'diary'
self.primary_key = 'DiaryNo'
has_many :animals, :foreign_key => 'DiaryQueue'
end
animal.rb
class Animal < ActiveRecord::Base
establish_connection :premvet
self.table_name = 'animal'
self.primary_key = 'PVID'
attr_accessible :AddedBy, :Age, :AnimalBFAmount, :AnimalBalance, :AnimalName, :Archive, :BillType, :Breed, :ChronicStatus, :Class, :Classification, :ClientKey, :Colour, :Date1, :DateOfBirth, :DateofBirth, :Dead, :DiaryQueue, :DiscField, :DrugsAtCost, :DrugsNoVAT, :ESDAmount, :ESDType, :FNote, :FirstRegisteredDate, :Height, :IDNumber, :Insured, :InsuredWith, :IsClient, :IsClientDate, :IsMaster, :LastBilledAmount, :LastBilledDate, :LastConsDate, :LastContributionDate, :LastPaidDate, :LastWeightDate, :Locked, :LoyaltyMultiplier, :LoyaltyPoints, :MR_Flag_0, :MR_Flag_1, :MR_Flag_10, :MR_Flag_11, :MR_Flag_12, :MR_Flag_13, :MR_Flag_14, :MR_Flag_15, :MR_Flag_2, :MR_Flag_3, :MR_Flag_4, :MR_Flag_5, :MR_Flag_6, :MR_Flag_7, :MR_Flag_7, :MR_Flag_8, :MR_Flag_9, :Mileage, :Neutered, :NextApptDate, :ORT, :OldSex, :Opt_Flag_0, :Opt_Flag_1, :Opt_Flag_2, :Opt_Flag_3, :Opt_Flag_4, :Opt_Flag_5, :Opt_Flag_6, :Opt_Flag_7, :PVID, :PreferredContact, :PreferredUser, :Ref1, :RefPrac, :ReferredBy, :SSDType, :SeenInPeriod, :SendBill, :Sex, :SiteAnimal, :Species, :Status, :SurcAmount, :SurcType, :SurgeryNumber, :TBU, :TOSAmount, :TOSDrugs, :TOSFees, :TOSType, :Weight
belongs_to :client, :foreign_key => 'ClientKey'
belongs_to :diary, :foreign_key => 'DiaryNo'
end
animals index view
<% #animals_todaysappointments.each do |animal| %>
<tr>
<td><%= animal.id %></td>
<td><%= animal.AnimalName %></td>
<td><%= link_to animal.client.Surname, animal.client %></td>
<td><%= animal.Species %></td>
<td><%= animal.Breed %></td>
<td><%= animal.NextApptDate.strftime("%d %b. %Y - %H:%M") %></td>
<td><%= animal.DiaryQueue %>
<td><%= animal.diary.DiaryName %></td>
<td><%= link_to 'Show', animal %></td>
</tr>
<% end %>
As you can see it's showing the DiaryQueue from the animal table using:
<td><%= animal.DiaryQueue %>
and I am trying to show the DiaryName from the diary table with:
<td><%= animal.diary.DiaryName %></td>
This fails with an exception error:
undefined method `DiaryName' for nil:NilClass
The #animals_todaysappointments method looks like this:
def appointments
#animals_todaysappointments = Animal.where('DATE(NextApptDate) = ?', Date.today).page(params[:page]).per_page(15).order('NextApptDate ASC')
respond_to do |format|
format.html # index.html.erb
end
end
If I add:
delegate :DiaryName, :to => :diary
to the animal model then I get the following error:
Animal#DiaryName delegated to diary.DiaryName, but diary is nil: #
Each animal record has a DiaryQueue value between 0 and 10 and the diary table has a number of rows, an example row is:
DiaryNo DiaryName DiaryDate SlotHour TotalSlots BlockBooked FreeSlot BookedSlot
--------------------------------------------------------------------------------------
1 Morning 2012-07-16 9 18 0 0 18
There are rows with the same DiaryNo, but they also have the same DiaryName. It's only the DiaryDate, SlotHour, TotalSlots, BlockBooked, FreeSlot and BookedSlot that alter in those rows.
To try and prevent the error I added the following to the view:
<% unless animal.DiaryName.nil? %>
<td><%= animal.DiaryName %></td>
<% else %>
<td><%= animal.DiaryQueue %>
<% end %>
but I get an exception:
Animal#DiaryName delegated to diary.DiaryName, but diary is nil: #
What am I doing wrong?
Given your answers above, you might need to change the belongs_to method in Animal to the following:
belongs_to :diary, :foreign_key => "DiaryQueue", :primary_key => "DiaryNo"
In your current implementation your models are going to try to match Animal#DiaryNo against Diary#DiaryNo, when what you've said you wanted is to match Animal#DiaryQueue against Diary#DiaryNo.
i have this in the controller
#ads = Ad.all(:joins => 'LEFT JOIN states ON ads.state_id = states.id')
but i have problem to query field of states table.
any idea?
<% #ads.each do |ad| %>
<tr>
<td><%= ad.title %></td> <- title is ad field.no problem
<td><%= ad.name %></td> <- name is states field.problem at here
</tr>
<% end %>
I don't think this will work unless you have associations set up. Unless performance is a concern, you may just want to use the association without joins
ad.rb
class Ad < ActiveRecord::Base
belongs_to :state
end
state.rb
class State < ActiveRecord::Base
has_many :ads
end
controller
#ads = Ad.all
view
<% #ads.each do |ad| %>
<tr>
<td><%= ad.title %></td>
<td>
<%= ad.state.name %>
</td>
</tr>
<% end %>
I think you need to put this: ads.state_id = states.id like this: #{ads.state_id = states.id}
The #{ } will evaluate the ruby code inside. Otherwise what you have is just text inside a string.
I'm not quite sure what your issue is, though, so I'm not totally sure that will fix it.