Skip to content

Instantly share code, notes, and snippets.

@dmzza
Forked from openfirmware/upload.rb
Last active December 10, 2016 09:13
Show Gist options
  • Save dmzza/ce9b6e660c576039afca984cda0f0aed to your computer and use it in GitHub Desktop.
Save dmzza/ce9b6e660c576039afca984cda0f0aed to your computer and use it in GitHub Desktop.
# Potential solution to "Using accepts_nested_attributes_for with a belongs_to association, and using find_or_create_by_attr behaviour"
# http://stackoverflow.com/questions/2970255/using-accepts-nested-attributes-for-with-a-belongs-to-association-and-using-find
class Upload < AR:B
belongs_to :user
belongs_to :observed_property
belongs_to :sensor
attr_accessor :observed_property_attributes,
:sensor_attributes
before_validation :update_associations, unless: "@observed_property_attributes.nil? || @sensor_attributes.nil?"
validate :validate_associations
def update_associations
observed_property = ObservedProperty.find_by(name: @observed_property_attributes[:name])
if observed_property.nil?
observed_property = ObservedProperty.new(@observed_property_attributes)
end
self.observed_property = observed_property
sensor = Sensor.find_by(name: @sensor_attributes[:name])
if sensor.nil?
sensor = Sensor.new(@sensor_attributes)
end
self.sensor = sensor
end
def validate_associations
merge_errors(observed_property) unless self.observed_property.valid?
merge_errors(sensor) unless self.sensor.valid?
end
def merge_errors(instance)
instance.errors.each do |att, msg|
if att == 'base'
errors.add("#{instance.class.to_s.downcase}_attributes", msg)
else
errors.add("#{instance.class.to_s.downcase}_attributes_#{att}", msg)
end
end
end
end
# Matching spec
# spec_helper.rb defines a few sample users
require 'spec_helper'
describe Upload do
before(:each) do
@valid_attributes = {
:observed_property_attributes => Factory.attributes_for(:observed_property, :creator => @user_a),
:sensor_attributes => Factory.attributes_for(:sensor, :creator => @user_a)
}
end
it "should create a new instance given valid attributes" do
upload = @user_a.uploads.create!(@valid_attributes)
upload.observed_property.should_not be_nil
upload.sensor.should_not be_nil
end
it "should use existing models when linked to them, regardless of creator" do
observed_property = Factory :observed_property, :creator => @user_b
sensor = Factory :sensor, :creator => @user_c
upload = @user_a.uploads.create!(
:observed_property_attributes => { :_id => observed_property._id },
:sensor_attributes => { :_id => sensor._id }
)
upload.observed_property.should == observed_property
upload.sensor.should == sensor
end
it "should not save with blank attributes" do
upload = @user_a.uploads.new
upload.observed_property = ObservedProperty.new
upload.sensor = Sensor.new
upload.update_attributes(
:observed_property_attributes => {
:_id => "",
:unit => "",
:description => ""
},
:sensor_attributes => {
:_id => "",
:description => ""
}
)
lambda {
upload.save!
}.should raise_error
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment