I Using accepts_nested_attributes_for to update has_many nested tables, Why not update but insert
diaries_controller.rb
def update
#diary=Diary.find(params[:id])
if #diary.update(update_diary_params)
render_ok
else
render_err :update_error
end
end
def update_diary_params
params.require(:diary).permit(:date,:weather,:remark, :diary_pictures_attributes=> [:diary_picture,:clothing_picture,:id,:_destroy])
end
model/diary.rb
class Diary < ApplicationRecord
has_many :diary_pictures,dependent: :destroy
accepts_nested_attributes_for :diary_pictures,allow_destroy: true
end
model/diary_picture.rb
class DiaryPicture < ApplicationRecord
belongs_to :diary
validates_presence_of :diary
end
enter image description here
Related
I'm trying to figure out how to automatically set up an invoice with invoice_rows, once a reservation is saved.
Attempts
Before even including the order_rows, I tried generating an invoice for order:
I tried including #order.invoices.create(order_contact_id: #order.order_contact_id) after saving the order in create, but this resulted in an empty array:
Order.last.invoice => []
Afterwards I probably should iterate over all products belonging to a order and include them as invoice_rows in invoice. But not sure how.
Note
The actual structure is more complex and consequently I need all my tables.
Code
models
class Order < ApplicationRecord
has_many :invoices
has_many :order_products, dependent: :destroy
end
class OrderProduct < ApplicationRecord
belongs_to :product
belongs_to :order
accepts_nested_attributes_for :product
end
class Product < ApplicationRecord
has_many :orders, through: :order_products
has_many :product_prices, dependent: :destroy, inverse_of: :product
accepts_nested_attributes_for :product_prices, allow_destroy: true
end
class ProductPrice < ApplicationRecord
belongs_to :product, inverse_of: :product_prices
end
orders_controller
class OrdersController < ApplicationController
def create
#order = #shop.orders.new(order_params)
authorize #order
if #order.save
authorize #order
# #order.invoices.create(order_contact_id: #order.order_contact_id)
redirect_to new_second_part_shop_order_path(#shop, #order)
end
end
private
def order_params
params.require(:order).permit(:order_contact_id,
order_products_attributes: [:id, :product_id, :product_quantity, :_destroy,
products_attributes: [:id, :name, :description]])
end
end
As suggested in the comments, I found the error message by using #order.invoices.create!.
Afterwards I iterated over each product and created an invoice_row for the created invoice.
#invoice = #order.invoices.create!(order_contact_id: #order.order_contact_id)
#order.order_products.each do |o_product|
#invoice.invoice_rows.create!(
description: o_product.product.name,
total_price: #reservation.total_product_price(#reservation, o_product)
)
end
I am currently struggling with a has_many :through association in my project.
This is my model
class Group < ActiveRecord::Base
has_many :user_groups ,dependent: :destroy
has_many :users , through: :user_groups
end
class User < ActiveRecord::Base
has_many :user_groups ,dependent: :destroy
has_many :groups , through: :user_groups
end
class UserGroup < ActiveRecord::Base
belongs_to :user , inverse_of: :placements
belongs_to :group , inverse_of: :placements
validates :level , presence: true
end
So when i tried to create new group but it didn't work out.
This is my controller
class GroupController < ApplicationController
def create
group = Group.new(group_params)
group.users << User.find_by(id: current_user.id)
if group.save
render json: group, status: 201, location: [group]
else
render json: { errors: group.errors }, status: 422
end
end
private
def group_params
params.require(:group).permit(:name, :shuttle_price, :court_price)
end
end
But when i call create method i got this error.
Could not find the inverse association for group (:placements in Group)
On this line
group.users << User.find_by(id: 6)
So how can i fix this?
Thanks!
Remove :inverse_of
class UserGroup < ActiveRecord::Base
belongs_to :user
belongs_to :group
validates :level , presence: true
end
You don't need to add inverse_of there. read this when to use inverse_of
A course has_many students and student has_many courses
Using a json API how would we update course to assign multiple students to a course
Model
class Course < ActiveRecord::Base
has_many :course_students
has_many :students, through: course_students
accepts_nested_attributes_for :course_students
end
class Student < ActiveRecord::Base
has_many :course_students
has_many :courses, through: course_students
end
class CourseStudent < ActiveRecord::Base
belongs_to :course
belongs_to :student
end
Controller
class CoursesController < SessionsController
def update
if #course.update_attributes(course_params)
puts "students should now be added to course"
end
end
def course_params
params.require(:course).permit(:description, :status, course_students_attributes: [:id], course_jobs_attributes: [:id])
end
end
Am I on the right path?
If your relationship is many to many, you are missing the keyword through in the association declaration:
class Course < ActiveRecord::Base
has_many :students, through: :course_students
accepts_nested_attributes_for :course_students
end
class Student < ActiveRecord::Base
has_many :courses, through: :course_students
end
http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association
Also be careful with accepts_nested_attributes_for, specially with validations. Here you can read more: https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through
My Models:
class Vip < ActiveRecord::Base
belongs_to :organization
has_many :events
has_many :organizations, :through => :events
end
class Organization < ActiveRecord::Base
belongs_to :user
has_many :events
has_many :vips, :through => :events
end
class Event < ActiveRecord::Base
belongs_to :organization
belongs_to :vip
end
My vips Controller:
def create
#organization = Organization.find(params[:organization_id])
#vip = #organization.vips.build(vip_params)
if #vip.save
redirect_to organization_path(#organization)
else
render 'new'
end
end
def vip_params
params.require(:vip).permit(:name, :about, :organization_id)
end
Before I started using the has_many :through associations, the build method would automatically add the foreign key to the new vip. So my vips table would have the organization_id column populated. Since using the has_many associations, the organization_id column is being left NULL on 'vip#create'.
Is there a reason that build wouldn't work the same way anymore with my new associations?
I've got two models
class Payment < ActiveRecord::Base
has_and_belongs_to_many :invoices
after_save :update_invoices_state
def update_invoices_state
self.invoices.each{|i| i.update_state }
end
end
class Invoice < ActiveRecord::Base
has_and_belongs_to_many :payments
def pending_value
paid_value = Money.new(0,self.currency)
self.payments.each{|payment| paid_value += payment.value}
self.value - paid_value
end
def update_state
if self.pending_value.cents >= 0
if self.due_on >= Time.zone.today
new_state = :past_due_date
else
new_state = :pending
end
else
new_state = :paid
end
self.update_attribute :state, new_state
end
end
I've been debuggin this and I've found that when invoice.update_state is run self.payments is empty. Looks like HABTM hasn't been updated yet.
How could i solve this?
I believe HABTM has been mostly replaced by has_many :through.
You would create a join model, something like "InvoicePayment" (or something else creative)
class Payment < ActiveRecord::Base
has_many :invoice_payments
has_many :invoices, :through => :invoicepayments
end
class InvoicePayment < ActiveRecord::Base
belongs_to :invoice
belongs_to :payment
end
class Invoice < ActiveRecord::Base
has_many :invoice_payments
has_many :payments, :through => :invoice_payments
end
This should fix your problem.