0

Ich versuche, diese Koordinaten aus den Metadaten des Bildes, das ich mit Büroklammer in eine andere Tabelle mit dem Namen places hochgeladen habe, zu veröffentlichen. "So gehen die Koordinaten zur Tabelle Orte." In der Tabelle Orte gibt es Spalten Längen- und Breitengrad. Nach dem Abschicken des Beitrags lief ich auf diesen Fehler. Der hervorgehobene Teil des Fehlers ist self.latitude = parse_latlong (etc ....).NoMethodError in PostsController # create undefined Methode `latitude = '" Speichern von Lat und Long zu verbundenen Tabellen !! "

post_id ist ein Fremdschlüssel in der Tabelle Orte. Dies funktionierte früher, als ich den Breiten- und Längengrad in der Post-Tabelle hatte. aber jetzt gab ich ihm eine eigene Tabelle für bessere Datenbankstruktur. ich muss nur wissen, wie man meinen Pfostensteuerpult erhält, um mit meinem Stellensteuerpult zu arbeiten, wenn das das Hauptproblem ist ??

Places-Controller

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 

Post Controller

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 

Post Modell

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 

Alles in Allem Ich mag würde, dass die Breiten- und Längen Variable in die Datenbank von der Aktualisierung erhalten Exif Extraktion .. die Extraktion ist nicht das Problem, aber ich glaube, wie ich das speichern Informationen in die Datenbank ist das wahre Problem !!! Danke!!!!

Antwort

1

Das Problem scheint aus der Tatsache, Einhalt zu gebieten, dass Sie Attribut von einem zugehörigen Modell aktualisieren. Sie könnten dies tun, indem

Aufruf

update_attributes(place_attributes: {latitude: , longitude: })

Aber ich würde empfehlen, diese Logik aus dem Pfosten Modell zu halten, das ist wirklich ein Problem für ein Formular Modell, in dem Sie die ungefilterte Benutzereingaben in eine Datenbank Verbrauch Format umwandeln. Wenn Sie Ihrer App keine zusätzliche Ebene hinzufügen möchten, verschieben Sie diese Methoden zumindest in ihr eigenes Modell. Jedesmal, Sie sind eine Gruppe von privaten Methode sehen einander aufrufen und Zustand um, ich denke, es ist ein gutes Zeichen, dass sie für eine Klasse sollte: So

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 

Als Hinweis würde ich auch MiniExiftool kapseln und injizieren es als eine Abhängigkeit im Konstruktor. Aber verlieren wir unser Ziel hier nicht aus den Augen.

Dann in Ihrem Controller können Sie Ihren Parser rufen Sie den Ort params

def place_params 
    long_lat_parser = LongLatParser(image) 
    {place_attributes: {longitude: long_lat_parser.lon, latitude: long_lat_parser.lat}} 
end 

zu geben und dann einfach sie in die Post params fusionieren:

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

Die benenfit dieses Ansatzes ist, dass Sie ein Objekt mit einer klaren Verantwortung eingeführt haben und als reines Datenbank-Wrapper zum AR-Modell zurückgekehrt sind. Im Allgemeinen versuche ich, komplexere Interaktionen in einer Art von Dienstobjekt zu kapseln, aber im einfachsten Fall kann Ihr Controller die Rolle eines Vermittlers spielen, der die Interaktion zwischen verschiedenen Objekten in Ihrem System koordiniert.

+0

in Ordnung! yea ich habe versucht, mich an ein platzmodell zu bewegen, aber wie kann ich das tun, ohne einen fehler zu werfen? ich bewege nur den privaten teil und behalte nach_post_prozess: save_latlong ?? Ich habe es schwer, Modelle und Controller zu verbinden, wenn ich versuche zu lernen !! –

+0

Ja, ich denke, das ist ein genereller Mangel, dass Ihnen das Framework nicht hilft, schauen Sie sich hier Formularmodelle an (ich bin gerade mobil, Ill aktualisiere die Antwort später mit einem Beispiel) https: //robots.thoughtbot .com/activemodel-form-objects –

+0

Beide von euch haben mir geholfen und ich habe alles zum arbeiten .. wenn du denkst, dass ich es in einem anderen model haben sollte und es dir nichts ausmachen würde, mir das zu zeigen, wäre das toll! Ich wünschte, ich könnte beide Beiträge eurer Jungs mögen !!! Danke!!! –

0

Statt:

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

Verwendung:

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

danke für die schnelle antwort !!! aber ich bekomme einen anderen Fehler es sagt unbekannten Attribut Fehler unbekannt Attribut 'Breite' für den Post ..... ich glaube, es hat mit der Tatsache zu tun, dass ich nicht lange oder lat in der Post-Tabelle haben, sondern in der Orte Tabelle –

+0

Oh ... Nun ja, das würde Sinn machen, haha! Das andere Problem, das ich mit dem obigen Code löse, ist, dass Ihr Code * die Daten * nach der Aktualisierung nicht speichern würde. Sie müssen entweder 'update_attributes' verwenden oder' save' explizit aufrufen. –

+0

Beachten Sie, dass die Verwendung der Methode 'update_attributes' die Modellvalidierungen überspringt. Wenn das ein Problem für Ihren Anwendungsfall ist, verwenden Sie stattdessen 'save' (oder' save! '). –