Rails 4 accepts nested attributes id can't be blank - ruby-on-rails

I am trying to update two models with one form. Everything seems to checkout, expect except both models will not save (not valid) because the required customer_order_id. How do I save the customer_order first, so that it will generate an id and then populate the payment?
def create
#customer_order = CustomerOrder.new(customer_order_params)
if current_user.id.present?
#customer_order.user_id = current_user.id
#customer_order.payments.first.user_id = current_user.id
end
respond_to do |format|
if #customer_order.save
format.html { redirect_to #customer_order, notice: 'Customer order was successfully created.' }
When I check if the model(s) are valid? here is the error.message
{:"payments.customer_order_id"=>["can't be blank"], :payments=>["is invalid"]}
It was my understanding that the customer_order would create the order first, then create the Payment. Thanks in advance for your help.

Validations run before saving to the database. It will be impossible to validate the presence of customer_order_id in this case since the customer order is not yet saved.
Consider validating the presence of customer_order instead. This allows the validation to pass when a customer order is present whether it is saved or not.
Caveat
When building records through associations and nested attributes ActiveRecord will make assignments based on inverse associations. In your case the inverse associations being used are payments (on CustomerOrder) and customer_order (on Payment). ActiveRecord will use those to set payment.customer_order correctly when a payment is built through nested attributes. If ActiveRecord in unable to determine the inverse associations (due to naming, joins in the associations, etc.) then you may need to explicily add the :inverse_of option to each association.

In your after create hook create the first payment ( in the customer_order model)
#Customer order model
after_create :create_first_payment
def create_first_payment
self.payments.create(user_id: user_id)
end

Related

Using after_create to update a cart's order_id

First, I have a cart stored in a session. The carts contain line items(products). The checkout button leads to a Order.new form with the cart_id passed to the new order(cart has_one order, order belongs_to cart).
Hopefully so far so good.
The cart params contains an order_id, that initially is nil, until the user hits the checkout button. When the order is created, the order_id in the cart is still nil. How can I use an after_create on the order model to update the cart to now have a valid order_id?
I have a current_cart method in my application controller, so I have access to current_cart in all my controllers, but I can't access it in the model -> as it is stored in a session and I've heard I don't want to be accessing sessions in the model anyway.
How one one recommend doing this?
I'll show some code in case my description wasn't clear.
orders_controller.rb
def create
#cart = current_cart
#order = #cart.build_order(order_params)
if #order.save
redirect_to #order, notice: "The order has been successfully created. Below are your shipping options."
else
render action: "new"
end
end
rails console
>> #order.cart.order_id
=> nil
Does it even really matter? Maybe I'm being paranoid, but I think it would be good practice to have access to the order_id from the cart as well as the cart_id from the order.
Thanks all,
Pat
You do not need to store the order_id in both directions, in fact you are probably creating more problems than you are hoping to solve with this design. For example, you will have to keep the value up to date in both directions, either when the order's cart changes or the other way around.
Rails is smart enough by itself to figure out which record is associated with which, even without an order_id on the Cart model:
cart = Cart.last
cart.order
#=> #<Order ...>
order = Order.last
order.cart
#=> #<Cart ...>
I also want to point out that you probably do not even need to persist Cart to the database, since it only makes sense in the context of a single browser session. You could instead design it as a plain old Ruby object (just a class, not inheriting from ActiveRecord::Base) and further simplify your design that way.

Rails HABTM - Properly removing an association

I am developing a feature for creating specials, for a shopping website. One product can have more than one special, and obviously a special can have more than one product..
I am using a has_and_belongs_to_many relationship, so i have declared:
Product.rb
has_and_belongs_to_many :specials
Special.rb
has_and belongs_to_many :products
Now, with a product #product and a special #special, an association is created like so..
#special.products << #product
After doing this, the following is true:
#special.products.first == #product
and, importantly:
#product.specials.first == #special
When i delete the association using this
#special.products.delete(#product)
then #product is removed from specials, so #special.products.first==nil, however #product still contains #special, in other words #products.specials.first==#special
Is there any proper way, apart from writing a delete method, to do this in a single call?
According to the Rails documentation:
collection.delete(object, …)
Removes one or more objects from the
collection by removing their associations from the join table. This
does not destroy the objects.
Brilliant reference here for you
You can use:
product = Product.find(x)
special = product.specials.find(y)
product.specials.delete(special)
This creates ActiveRecord objects for both the object you're trying to remove, which gives clear definition to the function
collection.clear
Removes all objects from the
collection by removing their associations from the join table. This
does not destroy the objects.
In this example:
product = Product.find(x)
product.specials.clear

Connecting a user model and event model in rails with foreign key?

--UPDATE: I've been doing some more reading and it looks like I should be adding a foreign key - could someone show me how I'd go about doing this? Should I be removing those extra fields I created?
--
I'm new to Ruby on Rails and I'm having trouble with some basic concepts. I've just finished Michael Hartl's book, and I'm using a RailsApps bootstrap-devise-cancan template to start on my first app.
I have a User model and an Event model. I want users to be able to post many events and also attend many events. I added the fields events_attending and created_events to the User table, and the Event table includes users_attending and user_created. I am trying to make it so that when the 'create an event' form is submitted, the user_created field is filled with whichever user posted the event, and that event id is recorded in the users table under created_events.
I've added to the Event model:
belongs_to :user
has_many :users
and to the User model (although I'm not sure if this is correct given that users can belong to multiple events. I looked into has_and_belongs_to_many and thought maybe that was the way to go..):
has_many :events
belongs_to :event
I'm lost as to what to put in the controllers to achieve the desired affect. This is what is currently in the events controller:
def create
#event = Event.new(params[:event])
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render json: #event, status: :created, location: #event }
else
format.html { render action: "new" }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
What should I be adding to the controller, and what else am I missing? Let me know if any more code needs to be seen. Thanks!
The answer to this question is available in the Rails guides and other places. It's clear that you have not grasped the basics of model relations and you should read up on it a bit more. I'll try to help you:
The Users has_many events is the relation for an event that a user has created. That relation is modeld in the database as a user_id column on the Event table. So when a user creates an event that users id is saved in the event record as user_id. Rails then gives you helper methods such as user.events to get all the events that the user has created.
The other relation, users attending events, needs a separate table. You can see why by examining the relation. The one between user and event above is a one to many relation, A user can cerate many events but each event belongs to exactly one user. The relation here is a many to many relation, an event can be visited by many users and each user can visit many events. There is no way to store that information in a normalized way in a relational database. No matter what side of the relation you look at, user or event, the data is an array...
The solution to this is a join table, a table where you have pairs of user_ids and event_ids. Rails can handle this kind of relation as well, it's called a has_and_belongs_to_many relation or habtm for short. Googling that will give you information on how to set it up and work with it.
I'll throw in another note: If you only want to look at the relation from one point of view, as in you will be calling user.event_visits but never event.visiting_users you can get away with a column in the user model and skip the join table. What you need is a serialized column of event_ids that you can then use to get all the events that user will visit. Working with the data this way is not normalized (and thus frowned upon by DBAs) but can be reasonable depending on your needs. It will require a bit more work on your part thoguh.

Update one model and create other model in one form Rails 3.2.5

I have one form that can create two models perfectly, but, is there any way to update one of the models and create the other?
Resuming:
I have a form for creating an appointment and also I can create the person for this appointment.
def new
#Cita = Cita.new
#Cita.build_paciente
render :new
end
def create
#Cita = Cita.new(params[:cita])
if #Cita.save
redirect_to :action => 'hoy'
else
render 'new'
end
This is working pretty well when I create the two models at time, but if I fill the person fields ...
How can I do for UPDATING the person attributes ("paciente") and creating the appointment ("Cita") for that person.
Thanks.
Finally I solved it adding a hidden field filling the person_ID on the person form. When you send the ID in the model attributes rails makes an update instead of an insert for that model while creates the other model associating the nested model.
If this hidden field is empty, rails create the two models at time.

Is there a more elegant way to do this in Rails (has_one association)

Hey, I'm very new to Ruby and Rails. I was wondering if I was doing this the right way.
#user = User.new(params[:user])
#student.user = #user
#student.save
if #user.save
...rest of the code
In my app, a Student has one User, and each User belongs to a Student (think of a User as an Account). The association itself isn't my question though; is the block of code above the best way to save a new User that's associated to a Student?
I'm surprised nobody mentioned the right way.
#user = #student.build_user(params[:user])
if #user.save
# ... rest of the code ...
end
This way #user will be built already associated with #student.
If the correspondence between user and student is 1:1 may be this relationship is redundant.
(maybe I'm missing something).
A cooler approach would be perform all the operations you need to the user object and then the last one would be:
#student.user = #user
#student.save
If the Student has_one User, then you should put the foreign key on the User. As in, the User will have the student_id column in the database. A user_id column on the Student isn't necessary.
In which case you can just do this:
#user = User.new(params[:user])
#user.student = #student
if #user.save
...rest of the code
And you won't even need to modify #student.
I think you have #-overload here. Only use # if you want to make the variable an instance variable of the class, rather than a local variable that only exists inside your function. Anyway, here's one possible way to do it:
#student.user = User.create(params[:user])
#student.save
if #student.user.new_record?
# didn't get saved...
end
ActiveRecord::Base#create creates a new object, tries to save it to the database, and then returns the object, and is a useful shortcut for the new-save pattern. It always returns the object, though, so you need to ask whether or not it was successfully saved, hence new_record?.
The question that comes up for me is whether the relationship between Student and User is a has-a or an is-a relationship. It has to do with object modeling of the domain problem.
I suspect it may be is-a, in which case you don't want has_one and belongs_to--known as "composition"--but instead Single-Table Inheritance (STI)--known as "inheritance".
The questions to ask are:
1. Is a Student also a User, i.e. does a Student have the same attributes and methods as a User, plus more methods or restrictions? Since in this case the Student IS also a user, the question of whether a Student can have 0, 1 or more Users does not apply.
2. Does the Student "have" a User in the sense that it could also have 0 Users, or perhaps more than 1?

Resources