I have a simple app where you can upload recipes
I have just integrated the gem terrarum to give me all the countries of the world within my country model. I have a relationship where a recipe has_one country and a country belongs to recipe. I am using nested forms from ryan bates and have had no problem getting information to show from my ingredients model and preparation model. But i cannot get the country name to save in the table or show in the view (though this is caused by not saving to model)
Code is as follows
Form
<%= f.label :country_id, "Country Of Origin" %>
<%= f.collection_select(:country_id, Country.all, :id, :name, :prompt => 'Please select country') %>
View
<% #recipes.each do |r| %>
<tr>
<td><%= r.dish_name %></td>
<td><%= r.country.name %></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>
Helper
def preperation_steps(preperations)
if preperations
preperation_array = preperations.map {|pre| pre.prep_steps}
preperation_array.join("\n")
end
end
def country_name(country)
if country
country_array = country.map {|c| c.country_name}
country_array.join("\n")
end
end
end
I have included my preparation helper as this works, so surely my country_name helper mirrors this? or do i not need to put a helper in for this?
recipe controller
def new
#recipes = current_user.recipes if current_user.recipes #show recipes if the user has any recipes
#favourites = current_user.favourites
end
recipe model
belongs_to :user
belongs_to :country
has_many :ingredients
has_many :preperations
has_many :favourites
attr_accessible :dish_name, :difficulty, :preperation_time, :ingredients_attributes, :preperations_attributes, :country_id, :avatar:preperations_attributes, :country_id, :avatar
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }
accepts_nested_attributes_for :ingredients, :preperations
scope :top_countries, order("country_of_origin DESC")
if anyone can help it would be much appreciated
Thanks
In this code I see two mistakes:
Recipe should belong_to :country. Don't use has_one here. The foreign key country_id should be in the recipes table.
#recipe.build_country is not necessary. You already have a list of countries. You should only use build_country if you are planning to add a new country to the list of countries, which you are not in this case.
Also, you don't need fields_for. You can just do:
<%= f.label :country_id, "Country Of Origin" %>
<%= f.collection_select(:country_id, Country.all, :id, :name, :prompt => 'Please select country') %>
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.
Again I'm faced with something that should not on the face of it be this difficult but has been driving me mad for an hour or so. I have multiple models which I want to pull into one 'index' view. I assume it's a join but I can't seem to find a way to do it.
What I have in my index view:
<% #tips.each do |tip| %>
<tr>
<td><%= tip.user_id %></td>
<td><%= tip.city_id # here I want to draw on the cities table to show city.name
%></td>
<td><%= tip.type_id # here I want to draw on the type table to show type.name
%></td>
<td><%= tip.place_id # here I want to draw on the place table to show place.name
%></td>
<td><%= tip.tip_desc %></td>
<td><%= link_to 'Show', tip %></td>
<td><%= link_to 'Edit', edit_tip_path(tip) %></td>
<td><%= link_to 'Destroy', tip, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
Here are the models:
class Tip < ActiveRecord::Base
belongs_to :user
belongs_to :city
belongs_to :place
end
class Place < ActiveRecord::Base
belongs_to :city
has_and_belongs_to_many :collections
has_many :tips
end
class City < ActiveRecord::Base
has_many :places
has_many :tips
end
Any help will be really appreciated!
Thanks in advance,
James
Suggestions from other guys should work. I'm not sure, but it seems like you don't have objects within specified IDs in your database. That's all :)
Example:
#tips.each do |tip|
tip.city_id # 1
City.find( tip.city_id ) # nil
end
I have the following code but can't render color as expected. When I render item.color I get #<Color:0x007ffce487a648>for example. If I render item.color.map(&:name) I get undefined method map for #<Color:0x007ffce6616918>
<% #this_week_orders.each do |order| %>
<tr style="font-weight:bold;">
<td><%= link_to "Order #{order.id}", order_path(order) %></td>
<td><%= l order.date, :format => :long %></td>
<td><%= pluralize(order.items.count, "item") %></td>
<td><%= number_to_currency(order.total_price) %></td>
<tr>
<% for item in order.items %>
<tr>
<td><li><%= item.product.name %></li></td>
<td><%= item.color %></td>
</tr>
<% end %>
<% end %>
Order has_many :items
Item belongs_to :order
Item belongs_to :product
Item belongs_to :color
scope :this_week, lambda { where("date > ?", 7.days.ago) }
Order controller
def this_week
#this_week_orders = Order.this_week.all
respond_to do |format|
format.html # index.html.erb
end
end
#<Color:0x007ffce487a648> reperesents an object of class Color (not a collection of color objects, whereupon it would make sense to use map). If Color has a name attribute, just write <%= item.color.name %>.
map is for use on an Array. item.color only returns one object. Use:
<%= item.color.name %>
if Color is a class like it appears to be you need to set the color value:
Something like:
<%= item.color.name %>
or whatever your value for the color is.
Greetings
I have 3 db tables:
Types
id
name
Sources
id
name
type_id
Operations
id
source_id
comment
...
and models for each:
class Type < ActiveRecord::Base
has_many :sources, :dependent => :destroy
end
class Source < ActiveRecord::Base
belongs_to :type
has_many :operations, :dependent => :destroy
end
class Operation < ActiveRecord::Base
belongs_to :source
default_scope :order => 'created_at DESC'
end
In Operation#index controller i have code for getting data (generated by scaffolding)
#operations = Operation.all
And piece of view operations/index.html.erb also generated by scaffolding
<% #operations.each do |operation| %>
<tr>
<td><%= operation.source_id %></td>
<td><%= operation.comment %></td>
</tr>
<% end %>
Now I want to use source.name instead of *operation.source_id*
I tried to do:
-replace operation.source_id to operation.sources.name # doesn't work
-tried to using :joins, and can't get Sources table fields
irb(main):057:0> Operation.first( :joins => :source )
=> #<Operation id: 2088, source_id: 1, summ: 10.0, comment: "", created_at: "2011-01-01 07:39:45", updated_at: nil>
or
irb(main):063:0> Operation.first( :joins => 'INNER JOIN sources ON operations.source_id = sources.id' )
=> #<Operation id: 2088, source_id: 1, summ: 10.0, comment: "", created_at: "2011-01-01 07:39:45", updated_at: nil>
How I must properly use :joins for get additional field?
Or there is another approach to get combined tables data.
And why in the operations/show.html.erb i can use <%= #operation.source.name %> and successfully get source.name, but in the *operations/index.html.er*b can't
<% #operations.each do |operation| %>
<tr>
<td><%= operation.source.name %></td>
<td><%= operation.comment %></td>
</tr>
<% end %>
I'd also recommend changing your #index method to use an includes statement to avoid an N+1 situation (i.e. running a separate database query for each individual operation's source).
#operations = Operation.includes(:source).all
Solved:
opearions#index
#operations = Operation.all :joins => :source, :select => '*'
operations/index.html.erb
<% #operations.each do |operation| %>
<tr>
<td><%= operation.name %></td>
...