Create / Update Resources via Rails 5 API with association - ruby-on-rails

I have a Match model with 2 players fields that have a belongs_to association with the User model
Model
class Match < ApplicationRecord
belongs_to :player1, :class_name => 'User', :foreign_key => 'player1'
belongs_to :player2, :class_name => 'User', :foreign_key => 'player2'
end
When creating a Match via the API (using a Postman POST request) I tried passing the user_id of the players but got a TypeMismatch error indicating the controller expected a User object but got a Fixnum.
Looking at this line:
#match = Match.new(match_params)
the error makes sense, so I modified my default scaffold generated controllers to look like this instead:
def create
#match = Match.new
#match.player1 = User.find(params[:match][:player1])
#match.player2 = User.find(params[:match][:player2])
if #match.save
render json: #match, status: :created, location: #match
else
render json: #match.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /matches/1
def update
if #match.update( :player1 => User.find(params[:match][:player1]),
:player2 => User.find(params[:match][:player2])
)
render json: #match
else
render json: #match.errors, status: :unprocessable_entity
end
end
It works, but the solution seems "inelegant".
Is there a better way to pass values to a controller with a belongs_to association?

Could you please try changing your foreign_key in Match model from player1, player2 to player1_id, player2_id respectively, via database migrations. Because your foreign_key and belongs_to associations are same? Please let me know whether it works!

Related

How to pass id from different table in rails?

Using Devise Gem to store user.
Created One to Many association between User to Project.
Created One to Many Association Between User and Site and Then One to Many Association between Project and Site.
But the error is i am not able to Assign project_id to Site from User Creation form. i am able to Assign from console. here is my code-
sites_controller.rb
def create
#site = current_user.sites.build(site_params)
respond_to do |format|
if #site.save
format.html { redirect_to #site, notice: 'Transactions was successfully Uploaded.' }
format.json { render :show, status: :created, location: #site }
else
format.html { render :new }
format.json { render json: #site.errors, status: :unprocessable_entity }
end
end
end
def site_params
params.require(:site).permit(:name, :amount)
end
site.rb(model)
belongs_to :user
belongs_to :project
User.rb
has_many :projects
has_many :sites
project.rb
has_many :sites, dependent: :destroy
How can i pass project_id on site creation. Is there any other simple way to resolve such problem?
Based on the comments in the question:
# project_id needs to be available to the method,
# in order to be added to site.
#
# Either pass it through params or get it from database
# based on your business logic.
site_params = site_params.merge({project_id: project_id})
#site = current_user.sites.build(site_params)
Should help.
Try permitting the foreign key as well.
def site_params
params.require(:site).permit(:name, :amount, :project_id)
end

rails : association tabel (has_and_belongs_to_many) not save any record

i use rails 5 , simple form. in my app there is a Category model and there is a OnlineProduct model. i dont know why when i want to add some categories to my OnlineProduct association table remain empty and don't change.
Category model:
class Category < ApplicationRecord
has_ancestry
has_and_belongs_to_many :internet_products
end
InternetProduct model:
class InternetProduct < ApplicationRecord
belongs_to :user
belongs_to :business
has_and_belongs_to_many :categories
end
InternetProduct controller:
def new
#internet_product = InternetProduct.new
end
def create
#internet_product = InternetProduct.new(internet_product_params)
respond_to do |format|
if #internet_product.save
format.html { redirect_to #internet_product, notice: 'Internet product was successfully created.' }
format.json { render :show, status: :created, location: #internet_product }
else
format.html { render :new }
format.json { render json: #internet_product.errors, status: :unprocessable_entity }
end
end
end
private:
def internet_product_params
params.require(:internet_product).permit(:name, :description, :mainpic, :terms_of_use,
:real_price, :price_discount, :percent_discount,
:start_date, :expire_date, :couponŲ€limitation, :slung,
:title, :meta_data, :meta_keyword, :enability, :status,
:like, :free_delivery, :garanty, :waranty, :money_back,
:user_id, :business_id,
categoriesŲ€attributes: [:id, :title])
end
and in the view only the part of who relate to categories :
<%= f.association :categories %>
all the categories list in view (form) but when i select some of them not save in database. in rails console i do this
p = InternetProduct.find(5)
p.categories = Category.find(1,2,3)
this save to database without any problem, what should i do ?
tanks for reading this
I found solution to solve this. when we use has_and_belong_to_many or any other relation , if you want to use collection select in simple_form , in the model also should be add this command for nesting form
accepts_nested_attributes_for :categories
also in the controller in related method for example in the new we should
def new
#internet_product = InternetProduct.new
#internet_product.categories.build
end

Rails - model association for recursive user model relationship

In my user model, I have
belongs_to :admin_creator, foreign_key: :created_by_user_id, class_name: "User"
and in my create controller action I have...
def create
#user = User.new(user_create_params)
#user.created_by_user_id = current_user.id
#user.status_code = 'P' #set status code to pending
begin
#user.save!
render json: "User #{#user.email} added", status: :created
rescue StandardError => e
render json: #user.errors.full_messages, status: :unprocessable_entity
end
end
How can I recast my code to to use model association for "current_user" who would be the admin_creator?
When create action is called, current_user is the current admin user who is adding another (child) user account. I'm thinking it would be along the lines of... #user = current_user.users.build(user_create_params) or similar
Add a has_many to the User model like this:
has_many :admin_children, foreign_key: :created_by_user_id, class_name: "User"
Then you can do:
current_user.admin_children.create(user_create_params)

in nested form- Can't mass-assign protected attributes:

I have read through several threads and nothing so far. I am trying to nest one form in another. I am getting the can't mass assign protected attributes error. \
app/controllers/projects_controller.rb:46:in new'
app/controllers/projects_controller.rb:46:increate'
Projects_controller.rb
def create
#project = Project.new(params[:project])
respond_to do |format|
if #project.save
format.html { redirect_to #project, notice: 'Project was successfully created.' }
format.json { render json: #project, status: :created, location: #project }
else
format.html { render action: "new" }
format.json { render json: #project.errors, status: :unprocessable_entity }
end
end
end
project.rb
WF::Application.routes.draw do
resources :line_items
resources :projects do
resources :line_items
end
devise_for :users
get 'about' => 'pages#about'
get 'Production' => 'projects#index'
root :to => 'pages#home'
end
here is the error...
ActiveModel::MassAssignmentSecurity::Error in ProjectsController#create
Can't mass-assign protected attributes: line_item
here is my project model
class Project < ActiveRecord::Base
attr_accessible :quantity
# may be unnessary
attr_accessible :line_items_attributes
belongs_to :user
has_many :line_items
accepts_nested_attributes_for :line_items, :allow_destroy => true
end
Assuming you're trying to create line items through your project model, you'll need to make sure you have the following lines in your Project model:
# project.rb
Class Project < ActiveRecord::Base
attr_accessible :line_items_attributes
accepts_nested_attributes_for :line_items
...
end
Rails is trying to protect you from accidentally assigning values you don't mean to.
You can tell Rails what values are ok to assign in this way:
attr_accessible :value1, :value2
If you add that line to the top of the Project model (replace :value1 and :value2 with the actual names of your columns), it should allow you to do what you're attempting.
For more info, here's the docs.

rails: Create does not work with :through in third model

So I have a nested resource with
resources :albums do
resources :elements
end
I can update, delete and view those elements.
What I can not really do is to create a new element.
So it is actually created in the database but not in the mapping table.
Models:
class Album:
has_many :elements, :through => :albums_elements
has_many :albums_elements
class Element:
has_many :albums_elements
has_one :album, :through => :albums_elements
class AlbumsElement:
belongs_to :album
belongs_to :element
In the element Controller I have:
def create
#element = Element.new(params[:element])
#album = Album.find(params[:album_id])
respond_to do |format|
if #element.save
format.html { redirect_to album_elements_path(#album), :notice => 'Element was successfully created.' }
format.json { render :json => #element, :status => :created, :location => #element }
else
format.html { render :action => "new" }
format.json { render :json => #element.errors, :status => :unprocessable_entity }
end
end
end
So as I said, when I press the create button in the form, the element is being created correctly in the table "elements", but not inserted into "albums_elements".
I saw a similar post here, where the author was told to fix his dependencies.
But I don't see an error in mines?
How do I tell rails to insert into both tables?
elements AND albums_elements?
Would you please check by relating your #element and #album in elements_controller class? Like you already have
#element = Element.new(params[:element])
#album = Album.find(params[:album_id])
Just add
#element.album = #album
Now #element.save should insert a entry in your relationship table also.
Let me know if it works. I've just answered after a glance to the problem.
Clarifications:
I will try to make a sample app for you. But before that i need to know some more.
Seems the relationship between Album and Element is one-to-many, then why you are using has_many :through? It could be simply Album: has_many :products and Product: belongs_to :album.
If you must use a relationship table, does it have any other attributes?
Is it OK if I provide any solution of one-to-many?
I will try to provide you the best rails way to save these entries asap.
Thnx

Resources