我正在尝试将使用回形针上传的图像的元数据中的这些坐标发布到另一个名为places的表格中。"所以坐标转到位置表格。"在places表中有列纬度和经度。提交帖子后我遇到了这个错误。突出显示的部分是self.latitude = parse_latlong(etc ....)。
post_id是places表中的外键。这在以前我在邮政桌上有纬度和经度时起作用。但现在我给了它自己的表以获得更好的数据库结构..我只需要知道如何让我的帖子控制器与我的位置控制器一起工作,如果这是主要的问题??
位置控制器
class PlacesController < ApplicationController
before_action :set_post
def create
@place = @post.places.build(place_params)
if @place.save
flash[:success] = "coorinates saved"
redirect_to :back
else
flash[:alert] = "Check the form, something went wrong."
render root_path
end
end
private
def place_params
params.require(:place).permit(:continent, :country, :city, :address, :latitude, :longitude)
end
def set_post
@post = Post.find(params[:post_id])
end
end
发布控制器
class PostsController < ApplicationController
before_action :authenticate_user!, :except => [:show, :index, :new]
before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :owned_post, only: [:edit, :update, :destroy]
def index
@post = Post.new
@posts = Post.all
end
def show
@post = Post.find(params[:id])
end
def new
@post = current_user.posts.build
@posts = Post.all
end
def create
@post = current_user.posts.build(post_params)
if @post.save
flash[:success] = "Your post has been created!"
redirect_to root_path
else
flash[:alert] = "Your new post couldn't be created! Please check the form."
render :new
end
end
def edit
@post = Post.find(params[:id])
end
def update
if @post.update(post_params)
flash[:success] = "Post updated."
redirect_to root_path
else
flash.now[:alert] = "Update failed. Please check the form."
render :edit
end
end
def destroy
@post.destroy
flash[:success] = "Your Post has been removed."
redirect_to root_path
end
private
def post_params
params.require(:post).permit(:image, :caption, :address)
end
def set_post
@post = Post.find(params[:id])
end
def owned_post
unless current_user == @post.user
flash[:alert] = "That post doesn't belong to you!"
redirect_to root_path
end
end
end
发布模型
class Post < ActiveRecord::Base
belongs_to :user
belongs_to :place
has_many :comments, dependent: :destroy
has_one :place, dependent: :destroy
validates :user_id, presence: true
validates :image, presence: true
accepts_nested_attributes_for :place
has_attached_file :image, styles: { :medium => "640x" }
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
after_post_process :save_latlong
private
def save_latlong
exif_data = MiniExiftool.new(image.queued_for_write[:original].path)
self.latitude = parse_latlong(exif_data['gpslatitude'])
self.longitude = parse_latlong(exif_data['gpslongitude'])
end
def parse_latlong(latlong)
return unless latlong
match, degrees, minutes, seconds, rotation = /(\d+) deg (\d+)' (.*)" (\w)/.match(latlong).to_a
calculate_latlong(degrees, minutes, seconds, rotation)
end
def calculate_latlong(degrees, minutes, seconds, rotation)
calculated_latlong = degrees.to_f + minutes.to_f/60 + seconds.to_f/3600
['S', 'W'].include?(rotation) ? -calculated_latlong : calculated_latlong
end
end
All in All我想将exitude和经度变量从exif提取更新到数据库中..提取不是问题但我相信如何将该信息保存到数据库中是真的问题!!!谢谢!!!!
答案 0 :(得分:1)
问题似乎源于您正在从关联模型更新属性。您可以通过调用
来完成此操作 update_attributes(place_attributes: {latitude: , longitude: })
但是我建议将这个逻辑保留在帖子模型之外,这实际上是表单模型的一个问题,您可以将原始用户输入转换为数据库可使用格式。如果您不想在应用中添加其他图层,请至少将这些方法移动到自己的模型中。 每次,你都会看到一组私人方法相互呼叫并传递状态,我认为这是一个很好的信号,他们应该为一个班级: 所以
class LotLangParser
def initialize(image)
@image = image
@exif_data = MiniExiftool.new(image.queued_for_write[:original].path)
end
def lat
parse_latlong(exif_data['gpslatitude'])
end
def lon
parse_latlong(exif_data['gpslongitude'])
end
private
def parse_latlong(latlong)
return unless latlong
match, degrees, minutes, seconds, rotation = /(\d+) deg (\d+)' (.*)" (\w)/.match(latlong).to_a
calculate_latlong(degrees, minutes, seconds, rotation)
end
def calculate_latlong(degrees, minutes, seconds, rotation)
calculated_latlong = degrees.to_f + minutes.to_f/60 + seconds.to_f/3600
['S', 'W'].include?(rotation) ? -calculated_latlong : calculated_latlong
end
end
作为一个注释,我还将封装MiniExiftool并将其作为构造函数中的依赖项注入。但是,让我们不要忘记我们的目标。
然后在您的控制器中,您可以调用解析器为您提供params
def place_params
long_lat_parser = LongLatParser(image)
{place_attributes: {longitude: long_lat_parser.lon, latitude: long_lat_parser.lat}}
end
然后简单地将它们合并到post params中:
@post = current_user.posts.build(post_params.merge(place_params))
这种方法的优点在于您引入了一个具有明确责任的对象,并将其作为数据库包装器返回到AR模型。一般来说,我尝试在某种服务对象中封装更复杂的交互,但在简单的情况下,您的控制器可以扮演调解器的角色,协调系统中不同对象的交互方式。
答案 1 :(得分:0)
而不是:
self.latitude = parse_latlong(exif_data['gpslatitude'])
self.longitude = parse_latlong(exif_data['gpslongitude'])
使用:
update_attributes(
latitude: parse_latlong(exif_data['gpslatitude']),
longitude: parse_latlong(exif_data['gpslongitude'])
)