Reputation: 417
Question UPDATED: I am trying to save the id of the current user whenever a purchase is edited. Specifically when a purchase is marked as received.
I have a before_update callback to a method that saves the datetime when the purchase is marked as received, that works well, I just need to figure out how to pass the purchase editor's id to the database.
In user.rb
class User < ActiveRecord::Base
has_many :purchase_edits, :foreign_key => :purchase_editor_id
has_many :edited_purchases, :through => :purchase_edits
has_many :created_purchases, :foreign_key => :creator_id, :class_name => "Purchase"
end
In purchase.rb
class Purchase < ActiveRecord::Base
belongs_to :vendor
belongs_to :creator, :class_name => "User"
has_many :purchase_edits, :foreign_key => :edited_purchase_id
has_many :editors, :through => :purchase_edits, :source => :purchase_editor
before_update :update_marked_received_date
## Saves date when marked received. ##
def update_marked_received_date
return unless received == true
self.marked_received = Time.now
end
end
In purchase_edit.rb (Join Table)
class PurchaseEdit < ActiveRecord::Base
belongs_to :purchase_editor, :class_name => "User"
belongs_to :edited_purchase, :class_name => "Purchase"
end
In purchases_controller.rb, (create & update), I have this:
def create
@vendor_options = Vendor.order("name ASC").all.map{ |u| [ u.name, u.id ] }
@purchase = Purchase.new(purchase_params)
@purchase.creator = current_user
if @purchase.save
redirect_to @purchase
else
render 'new'
end
end
def update
@vendor = Vendor.all
@vendor_options = Vendor.order("name ASC").all.map{ |u| [ u.name, u.id ] }
@purchase = Purchase.find(params[:id])
if @purchase.update(purchase_params)
flash[:notice] = 'Update successful.'
redirect_to @purchase
else
render 'edit'
end
end
In Schema.rb
create_table "purchases", force: :cascade do |t|
t.integer "vendor_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "order_number"
t.string "tradegecko_url"
t.integer "creator_id"
t.boolean "received", default: false, null: false
t.date "estimated_ship_date"
t.boolean "closed", default: false, null: false
t.datetime "marked_received"
end
create_table "purchase_edits", id: false, force: :cascade do |t|
t.integer "purchase_editor_id", null: false
t.integer "edited_purchase_id", null: false
end
create_table "users", force: :cascade do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0, null: false
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.inet "current_sign_in_ip"
t.inet "last_sign_in_ip"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "admin", default: false
end
Upvotes: 1
Views: 662
Reputation: 417
For anyone else who comes across this question, (and my future self), this is how I got it to work:
First, in application_controller.rb:
class ApplicationController < ActionController::Base
before_action :set_current_user
def set_current_user
User.current = current_user
end
end
Then in user.rb:
class User < ActiveRecord::Base
has_many :created_purchases, class_name: 'Purchase', foreign_key: 'creator_id'
has_many :received_purchases, class_name: 'Purchase', foreign_key: 'receiver_id'
def self.current
Thread.current[:user]
end
def self.current=(user)
Thread.current[:user] = user
end
def purchases
Purchase.where("creator_id = ? OR receiver_id = ?", self.id, self.id)
end
end
Finally, in purchase.rb:
class Purchase < ActiveRecord::Base
belongs_to :creator, class_name: "User", foreign_key: "creator_id"
belongs_to :receiver, class_name: "User", foreign_key: "receiver_id"
before_update :update_marked_received
def update_marked_received
return unless received == true
if self.marked_received.blank?
self.marked_received = Time.now
self.receiver_id = User.current.id
end
end
end
Now, when a purchase is marked as received, the timestamp and user are recorded.
Upvotes: 1
Reputation: 459
Class Purchase
belongs_to :created_by, class_name: 'User', foreign_key: 'created_by_id'
has_one :marked
end
Class Marked
belongs_to :purchase
belongs_to :user
end
This could work in your favour. Moreover, you could keep the relation has_one
or has_many
marked, according to your requirement.
I would recommend you to create a different model for this because it will be easier to maintain and the approach you are trying to achieve is violation of single responsibility principle. The model Marked will have a foreign key of two models because it has a relationship belongs_to for both the model. Please have a look of belongs to association.
Upvotes: 0