I created a nested model for two locations. I use a method to count the distance between these two locations. I'd like to take statistics to count all the distances weekly and show it in a view like this:
Week 1 - 80 kms / Week 2 - 32 kms
Could someone help me with it?
#edit
Getting distance:
<% #distance = Geocoder::Calculations.distance_between(#trip.locations.first, #trip.locations.last) %>
Trip model:
class Trip < ActiveRecord::Base
has_many :locations
accepts_nested_attributes_for :locations
end
Location model:
class Location < ActiveRecord::Base
belongs_to :trip
extend Geocoder::Model::ActiveRecord
geocoded_by :address
after_validation :geocode, :if => :address_changed?
end
Trips controller:
def index
#trips = Trip.all
#trip = Trip.new
2.times { location = #trip.locations.build }
end
def show
#trip = Trip.includes(:locations).find(params[:id])
end
And I get the locations from a field_for form
also routes:
resources :trips
root 'trips#index'
Related
I have 3 relevant models in a Rails 4 app - Charge:
class Charge < ActiveRecord::Base
belongs_to :rate
belongs_to :shift
def total
self.rate.value * self.quantity
end
end
Rate:
class Rate < ActiveRecord::Base
has_many :charges
end
and Shift:
class Shift < ActiveRecord::Base
has_many :charges
def total_charge
self.charges.sum('total')
end
end
I'm attempting to use shift.total_charge in my view, but I'm getting the error:
SQLite3::SQLException: no such column: total: SELECT SUM(total) FROM "charges" WHERE "charges"."shift_id" = ?
So it seems that it isn't possible to define total in the Charge model in this way, and have it accessible to sum from the Shift model as an actual column would be. I'm struggling to find the appropriate Rails 4 way of doing this - is it possible to do this in the model, or do I need to create a controller for Charge and try to do the calculation there?
sum works only with columns. You could use something like
class Shift < ActiveRecord::Base
has_many :charges
def total_charge
self.charges.map {|c| c.rate.value * c.quantity }.sum
end
end
and to avoid n+1 problem include Rate in Charge
class Charge < ActiveRecord::Base
belongs_to :rate
belongs_to :shift
default_scope {includes :rate}
end
I'm trying to make a simple app that records your trips. In should get two locations (via nested model) and then show distance between them in /show~
Unfortunately, I can make a new trip, but I can't get the view for the distance. However, if I want to put 'location.address' it doesn't work too.
trip controller:
def index
#trips = Trip.all
#trip = Trip.new
2.times do
location = #trip.locations.build
end
end
def show
#trip = Trip.includes(:locations).find(params[:id])
end
location model:
class Location < ActiveRecord::Base
belongs_to :trip
extend Geocoder::Model::ActiveRecord
geocoded_by :address
after_validation :geocode, :if => :address_changed?
end
trip model:
class Trip < ActiveRecord::Base
has_many :locations
accepts_nested_attributes_for :locations
end
show view for trips:
<% for location in #trip.locations %>
<li><%= location.distance %></li>
<% end %>
I'd appreciate any help.
Edit:
Ok, so I found how to calculate distance between specific places, but I don't know how to add two locations from one nested model to this code?:
#distance = Geocoder::Calculations.distance_between([place1], [place2])
I have this in my config/routes.rb:
get '/:category/:region', to: 'categories#filtered_by_region'
The filtered_by_region action is as shown below:
#filtered_by_region method
def filtered_by_region
#region = Region.where(title: params[:region]).first
#category = Category.where(title: params[:category]).first
#teams = Team.where(region_id: #region.id, category_id: #category.id)
end
I have a view filtered_by_region.html.erb that looks as follows:
Region: <%= #region.title %>
Category: <%= #category.title %>
<% #teams.each do |team|%>
<%=team.title %>
<% end %>
region.rb model is as follows:
class Region < ActiveRecord::Base
has_many :teams
attr_accessible :title
end
category.rb model is as follows:
class Category < ActiveRecord::Base
has_many :teams
attr_accessible :title
end
team.rb model is as shown below
class Team < ActiveRecord::Base
belongs_to :category
belongs_to :region
end
I also have the corresponding regions, teams and categories tables already populated with data.
when i enter a url that looks like this:
http://localhost:3000/football/south_west
i get an error with the following message:
undefined method ``title' for nil:NilClass I have realized both the #region and #category are returning nil but i do not understand why. i do have a category with football title and a region with south_west title in categories and regions tables respectively.
Why don't you use find_by (if you're using Rails 4) or find_by_title (if you're using Rails 3):
def filtered_by_region
#category = Category.find_by_title(params[:category])
#region = Region.find_by_title(params[:title])
if defined?(#category) && defined?(#region)
#teams = Team.where(region_id: region.id, category_id: category.id)
else
redirect_to root_path
end
end
I think the likely issue will either be your query is not finding any records, or you'll be trying to access a collection as a record (regardless of the use of .first)
I have 3 models; Product, Tax and Location. Whenever a product gets created I want to assign the latest tax of the location if it has a tax.
class Location < ActiveRecord::Base
belongs_to :user
has_many :products
has_many :taxes
end
class Tax < ActiveRecord::Base
attr_accessible :date # I use this to get the latest tax
belongs_to :location
has_many :products
end
class Product < ActiveRecord::Base
attr_accessible :tax_id
belongs_to :location
belongs_to :tax
end
Now I tried this in my Product model:
after_create :assign_latest_location_tax
private
def assign_latest_location_tax
if self.location.tax.present?
self.tax_id = self.location.tax.order("date DESC").first.id
end
end
But this gives me the error:
NoMethodError in ProductsController#create
undefined method `tax' for #<Location:0x4669bf0>
What is the correct way to do this?
Location has_many taxes, therefore the method it exposes to access it's taxes is taxes, not tax.
The following should work:
self.tax_id = self.location.taxes.order("date DESC").first.id
And if you use the after_create callback you must call save again on the end of it. To avoid this, you may use the before_create callback.
This code should work:
def assign_latest_location_tax
if self.location.taxes.count > 0
self.tax_id = self.location.taxes.order("date DESC").first.id
end
end
I have a nested forms like:
class House < ActiveRecord::Base
has_many :rooms
accepts_nested_attributes_for :rooms
attr_accessible :rooms_attributes
end
class Room < ActiveRecord::Base
has_one :tv
accepts_nested_attributes_for :tv
attr_accessible :tv_attributes
end
class Tv
belongs_to :user
attr_accessible :manufacturer
validates_presence_of :user
end
Now, I want to know for house.id = 1 how many rooms and tvs totally.
In the houses_controller I gave
#houses = House.all
And it's quit simple to get the room count for each house like
<% for house in #houses %>
<%= house.rooms.count %>
<% end -%>
My question is how to get tvs count? I am using this now
<%= house.rooms.map {|room| room.tvs.count}.sum %>
It works, but I am not sure this is good or not.
Is there any better way to get it?
I'd put a method in the model, trying to avoid code in the views.
class House
...
def tvs
rooms.inject(0) {|r, t| t + r.tvs }
end
end
class Room
...
def tvs
tv ? 1 : 0 # it's has_one association right now
end
end
Also, if in your controller your are loading all House's objects, and after that you are going to need the Rooms objects, you should load the houses like:
House.find :all, :include => { :rooms => :tv }
This way you are going to do 1 query, with your approach there will be 1 + N_rooms + N_tvs queries