This is very weird and I don't get it.
I got a polymorphic new form for storing address, the create method doesn't actually create the association.
location/new
%= form_for [@mappable, @location] do |form| %>
<div class="inline-label-container">
<%= form.label :street_address, "street address", :class => "inline" %>
<%= form.text_field :street_address, :onkeyup => 'timed_input(this)', :value => current_user.location.address, :autocomplete => :off %>
<%= form.label :location_description, "Found Location"%>
<%= form.text_field :address, :value => @user.location.address, :disabled => :true%>
<%= form.hidden_field :google_address, :value => @user.location.address %>
<%= form.hidden_field :latitude, :value => @user.location.latitude %>
<%= form.hidden_field :longitude, :value => @user.location.longitude %>
<%= form.submit "Enter Location", :class => "btn btn-large btn-success" %>
you can also drag and drop marker!
<small>
</small>
</div>
<%end%>
location_controller.rb
def new
@user = current_user
@mappable = load_mappable
@location = @mappable.build_location
end
def create
@user = current_user
@mappable = load_mappable
@location = @mappable.build_location(params[:location], :mappable_id => @mappable.id, :mappable_type => @mappable.class.base_class.name)
respond_to do |format|
if @location.save
format.html { redirect_to :back, notice: "#{@mappable.id}, #{@mappable.class.base_class.name}"}
format.json { render :json => :back, :status => :created, :location => @user }
#redirect_to @commentable, notice: "Comment created."
else
format.html { redirect_to root_path }
format.json { render :json => @location.errors, :status => :unprocessable_entity }
#render :new
end
end
def load_mappable
resource, id = request.path.split('/')[1,2]
@mappable = resource.singularize.classify.constantize.find(id)
end
In create method passing mappable_id and type were my last attempts to get them. It really odd because in the after create notice the correct mappable_id and mappable_type are displayed
2.1.1 :085 > Location.last
Location Load (0.6ms) SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT 1
=> #<Location id: 95, address: nil, longitude: -74.009457, latitude: 40.704513, postcode: nil, created_at: "2014-06-01 19:06:19",
updated_at: "2014-06-01 19:06:20", actor_id: nil, country: nil, country_code: nil, postal_code: nil, city: nil, political: nil, loc
ality: nil, sublocality: nil, street_address: "108 Pearl Street", google_address: "108 Pearl Street, New York, NY 10004, USA", ward
_id: nil, **mappable_id: nil**, mappable_type: "Skill">
why is mappable_id missing ? please help
Location.rb
class Location < ActiveRecord::Base
include ActiveModel::Validations
belongs_to :mappable, :polymorphic => true
searchkick
has_one :map, :dependent => :destroy
has_one :group, :through => :map, :source => :mappable, :source_type => 'Group'
belongs_to :ward
accepts_nested_attributes_for :ward
has_one :localfeed
attr_accessible :address, :latitude, :longitude, :postcode, :user_id, :actor_id, :group_id,
:country,
:country_code,
:postal_code,
:city,
:political,
:locality,
:sublocality,
:street_address,
:google_address,
:location_attributes,
:mappable_id,
:mappable_type,
:ward_id
geocoded_by :to_s
#before_save :geolocate
validate :street_address, :address_validator => true
after_validation :geocode
#before_save :geolocate
after_save :createward
#after_save :ward_present #creates new ward and feed if not existant
def address_changed?
attrs = %w(street_address city postal_code)
attrs.any?{|a| send "#{a}_changed?"}
end
def to_s
"#{google_address} #{city} #{postal_code}" +" GB"
end
def gmaps4rails_address
address
end
def ward_present
if self.ward_id = nil?
w = Ward.find_by_name(self.city)
self.ward_id = w.id
else
self.destroy
end
end
geocoded_by :to_s do |prof,results|
if result = results.select{|res| res.country_code == "GB" }.first
unless (result.latitude.nil? || result.longitude.nil?)
prof.latitude = result.latitude
prof.longitude = result.longitude
prof.country = result.country
prof.postal_code = result.postal_code
prof.city = result.city
#prof.political = result.political
# prof.locality = result.locality
# prof.sublocality = result.sublocality
prof.street_address = result.street_address
end
result.coordinates
end
end
def geolocate
res = GoogleGeocoder.geocode(to_s)
if res.success
self.latitude = res.latitude
self.lonitude = res.longitude
else
errors[:base] << "geocoding failed, check address"
return false
end
end
def createward
unless self.city.nil?
w = Ward.find_by_name(self.city)
if w.nil?
c = self.create_ward!({:name => self.city, :city => self.city}) # should be [name => self.sublocality]
self.ward_id = c.id
else
self.ward_id = w.id
end
end
end
def self.groups
self.where(:user_id => nil)
end
def self.users
self.where(:group_id => nil)
end
def self.users_city(city)
self.where(:mappable_type => "User", :city => city).map(&:mappable_id).uniq
#returns array of user_ids!
end
def search_and_fill_latlng(address=nil)
okresponse = false
geocoder = "http://maps.googleapis.com/maps/api/geocode/json?sensor=false&address="
if address == nil
address = self.address
end
if address != nil && address != ""
url = URI.escape(geocoder+address)
resp = RestClient.get(url)
result = JSON.parse(resp.body)
if result["status"] == "OK"
self.latitude = result["results"][0]["geometry"]["location"]["lat"]
self.longitude = result["results"][0]["geometry"]["location"]["lng"]
okresponse = true
end
end
okresponse
end
end
Skill.rb
class Skill < ActiveRecord::Base
attr_accessible :avatar_attributes, :photo_attributes, :name, :description,:skill_type_id, :properties, :teachers_title, :necessary_resources, :level, :required_experience,
:price, :start_date, :min_students, :max_students, :activity_duration, :location_id, :user_id, :location_attributes, :skill_type_attributes
belongs_to :user
belongs_to :skill_type
has_one :ward, :as => :warded
accepts_nested_attributes_for :skill_type
has_one :location, :as => :mappable
accepts_nested_attributes_for :location
included both model classes the location and skill.
Console
Started POST "/skills/10/locations" for 127.0.0.1 at 2014-06-02 13:11:32 +0100
Processing by LocationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"hgJxwarAwYS4RP3GidzBnd3MRShCnvDltb0r6ULblBo=", "location"=>{"street_address"=>"1
01 Pearl Street cardiff", "google_address"=>"101 Pearl Street, Cardiff CF24 1NE, UK", "latitude"=>"51.4866055", "longitude"=>"-3.15
24131999999554"}, "commit"=>"Enter Location", "skill_id"=>"10"}
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" = 6 LIMIT 1
Location Load (0.6ms) SELECT "locations".* FROM "locations" WHERE "locations"."mappable_id" = 6 AND "locations"."mappable_type"
= 'User' LIMIT 1
Avatar Load (0.5ms) SELECT "avatars".* FROM "avatars" WHERE "avatars"."avatarable_id" = 6 AND "avatars"."avatarable_type" = 'Use
r' LIMIT 1
Profile Load (0.5ms) SELECT "profiles".* FROM "profiles" WHERE "profiles"."user_id" = 6 LIMIT 1
Skill Load (0.4ms) SELECT "skills".* FROM "skills" WHERE "skills"."id" = $1 LIMIT 1 [["id", "10"]]
CACHE (0.0ms) SELECT "skills".* FROM "skills" WHERE "skills"."id" = $1 LIMIT 1 [["id", "10"]]
Location Load (0.6ms) SELECT "locations".* FROM "locations" WHERE "locations"."mappable_id" = 10 AND "locations"."mappable_type"
= 'Skill' LIMIT 1
(0.1ms) BEGIN
SQL (0.8ms) INSERT INTO "locations" ("actor_id", "address", "city", "country", "country_code", "created_at", "google_address", "
latitude", "locality", "longitude", "mappable_id", "mappable_type", "political", "postal_code", "postcode", "street_address", "subl
ocality", "updated_at", "ward_id") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19) RE
TURNING "id" [["actor_id", nil], ["address", nil], ["city", "Cardiff"], ["country", "United Kingdom"], ["country_code", nil], ["cr
eated_at", Mon, 02 Jun 2014 12:11:33 UTC +00:00], ["google_address", "101 Pearl Street, Cardiff CF24 1NE, UK"], ["latitude", 51.486
6055], ["locality", nil], ["longitude", -3.1524132], ["mappable_id", 10], ["mappable_type", "Skill"], ["political", nil], ["postal_
code", "CF24 1NE"], ["postcode", nil], ["street_address", "101 Pearl Street"], ["sublocality", nil], ["updated_at", Mon, 02 Jun 201
4 12:11:33 UTC +00:00], ["ward_id", nil]]
Ward Load (0.5ms) SELECT "wards".* FROM "wards" WHERE "wards"."name" = 'Cardiff' LIMIT 1
(0.8ms) COMMIT
I don't exactly know why, but the problem was with the Location controller #new method.
I changed the @location = @mappable.build_location
to @location = Location.new
and it started to work.