0

私はplaceclという別のテーブルにpaperclipを使ってアップロードした画像のメタデータからこれらの座標を投稿しようとしています。場所テーブルには緯度と経度の列があります。投稿を提出した後、私はこのエラーに遭遇します。エラーの強調表示された部分はself.latitude = parse_latlong(etc ....)です。NoMethodError in PostsController#未定義のメソッドを作成する 'latitude =' "緯度と経度を接続したテーブルを保存する!!"

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 

ポストモデルiはからデータベースに更新され、その緯度と経度変数を取得したいすべてに

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 

すべてexif抽出..抽出は問題ではありませんが、代わりにどのように私はそれを保存すると信じていますデータベースへの情報は真の問題です!ありがとうございました!!!!

self.latitude = parse_latlong(exif_data['gpslatitude']) 
self.longitude = parse_latlong(exif_data['gpslongitude']) 

使用:代わりの

答えて

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 

のparamsあなたに場所を与えるためにあなたのパーサを呼び出すことができ:

@post = current_user.posts.build(post_params.merge(place_params))

このアプローチのbenenfit明確な責任を持ってオブジェクトを導入し、単なるデータベースラッパーとしてARモデルに戻したということです。一般的には、ある種のサービスオブジェクトでより複雑なやりとりをカプセル化しようとしますが、単純なケースでは、コントローラが、システム内のさまざまなオブジェクトがどのようにやりとりするかを調整するメディエーターの役割を果たすことができます。

+0

大丈夫です!うん、私は前にモデルを配置するために移動しようとしたが、私はエラーをスローせずに私はそれを行うことができます私はちょうどプライベート部分を移動し、after_post_processを維持する:save_latlong ??私は勉強しようとしているモデルやコントローラを接続するのは苦労しています! –

+0

そうですね、これはフレームワークが大いに役に立たないという一般的な欠点だと思います。ここでフォームモデルを使用してみましょう(私は今、モバイルで作業しています。後で例をあげて答えてください)https://robots.thoughtbot .com/activemodel-form-objects –

+0

皆さんは私を助けてくれました。私はそれを仕事に費やしました。私は別のモデルでそれを持っていなければならないと思ったら、私は両方のあなたの人の投稿が好きになることを願っています!ありがとうございました!!! –

0

update_attributes(
    latitude: parse_latlong(exif_data['gpslatitude']), 
    longitude: parse_latlong(exif_data['gpslongitude']) 
) 
+0

高速返信ありがとうございます。しかし、別のエラーが表示されています。未知の属性のエラーは、未知の属性 '緯度'のポスト.....と言います。私は、ポストテーブルではなく、場所テーブルの長さまたは緯度を持たないという事実と関連しています。 –

+0

...うん、そう、それはその後、ハハを意味するだろう!上記のコードで解決しているもう1つの問題は、コードを更新した後で*データを保存しないということです。したがって、 'update_attributes'を使うか、' save'を明示的に呼び出す必要があります。 –

+0

メソッド 'update_attributes'を使用すると、モデル検証がスキップされることに注意してください。それがあなたのユースケースの問題ならば、代わりに 'save'(または' save! ')を使用してください。 –

関連する問題