Reputation: 54949
I have two Models Order(id, user_id,...)
and OrderEvent(id, order_id, ...)
the data of these are stored in two Objects @order
and @order_event
.
Now i want to save Order and update the order_id in OrderEvent and then save the content in the database.
In CakePHP if we had the content structured in a certain way we could save all of these together at once. Is there a way to save the content in a single call so that if there is any validation error both records are not created and fails
Order
--- !ruby/object:Order
attributes:
id:
host_id: 1
user_id: 1
order_no: PH1504-F3D11353
type_of_order: events
order_date: !ruby/object:DateTime 2015-04-17 10:49:52.066168000 Z
sub_total: 7050.0
tax_rate:
rate_cost:
deliver_charges:
discount_code:
discount_rate:
discount_cost:
total_cost: 7050.0
order_dishes_count:
order_events_count:
status: 0
created_at:
updated_at:
OrderEvent
--- !ruby/object:OrderEvent
attributes:
id:
order_id:
event_id: 2
no_of_ppl: 3
event_date: 2015-01-22 00:00:00.000000000 Z
cost: 2350.0
total_cost: 7050.0
status: 0
created_at:
updated_at:
Order
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :host
has_many :order_events
has_many :messages
end
OrderEvent
class OrderEvent < ActiveRecord::Base
belongs_to :event
belongs_to :order
end
Upvotes: 3
Views: 3048
Reputation: 700
Inverse_of and accepts_nested_attributes_for allow you to create two associated objects at the same time. Your models should be something like:
class Order < ActiveRecord::Base
has_many :order_events, inverse_of: :order
accepts_nested_attributes_for :order_events
end
class OrderEvent < ActiveRecord::Base
belongs_to :order, inverse_of: :order_event
end
In the orders controller:
def new
@order = Order.new
@order.order_events.build
end
def create
@order = Order.new(order_params)
...
end
Allow order_events attributes in the params:
def order_params
params.require(:order).permit(order_event_attributes: [])
end
In the form:
<%= form_for @order do |f| %>
<%= f.fields_for :order_events do |event| %>
<!-- event fields go here -->
<% end %>
Here is an article with more details what invese_of does: http://viget.com/extend/exploring-the-inverse-of-option-on-rails-model-associations
Upvotes: 3
Reputation: 1159
What you are looking for might be :
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
If you only want to update the OrderEvent just do
class OrderEvent
belongs_to :order
end
And in your controller
@order_event.update_attributes(order: @order)
Edit : update_attributes saves to the database.
See http://apidock.com/rails/ActiveRecord/Persistence/update for more info.
If you have both models ready but none has an id yet then I think you should go for nested attributes :
class Order
accepts_nested_attributes_for :order_events
has_many :order_events
end
class OrderEvent
belongs_to :order
end
I controller, In order to save the Order, with its order_events :
def update
@order.update_attributes(order_events_attributes: [@order_event])
end
Should work like a charm.
Upvotes: 1
Reputation: 9747
If you have set proper associations, following will work for you:
@order = Order.create(...)
@order_event = @order.order_events.create(...) # pass all attrs except id & order_id
EDIT:
If I have the object ready and just wanna save can I use '.save' instead of .create – Harsha M V
In that case, you can directly update @order_event
as:
@order_event.update(:order => @order)
Upvotes: 1
Reputation: 3072
Best way is to use Transactions of rails. Reference : Transactions
Upvotes: 1