I have a product model and a kit model through a KitProducts join table.
Product model
has and belongs to many kits
Kit model
has and belongs to many products
How can I get an output of my products with their kit_id in my JSON?
#products = Product.all
respond_to do |format|
format.html { render 'new', layout: "builder" }
format.json do
render json: [
products: #products
]
end
This will give me only the product itself, I need to be able to show their kit info
Desired JSON output:
products":[{"id":1,"name":"Test", "kit_id": 1}]
I want to be able to do kit.products in my JS file
You can use the include option in your render call:
Example:
render json: #products, include: :kit
This will give you the following output:
[{"id":1,"name":"Test", "kit_id": 1}]
If you want to include more than one association, you can pass an array:
render json: #products, include: [:kit, :other_association]
Related
Hi I am currently working on a web marketplace app for an assignment that allows users to upload items for sale with images attached, and to edit those listings.
Currently i have utilised simple forms for the edit and add product pages and those work fine but when I click update or add product I get the below error:
ActiveSupport::MessageVerifier::InvalidSignature in ProductsController#create
the error pointed out that line 3 of the below code is the problem:
def create
#product = Product.new(product_params)
#product.user_id = current_user.id
respond_to do |format|
if #product.save
format.html { redirect_to #product, notice: "Product was successfully created." }
format.json { render :show, status: :created, location: #product }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #product.errors, status: :unprocessable_entity }
end
end
end
My product.rb file looks as such:
belongs_to :user, :optional => true
has_one_attached :picture
end
The simple forms work but for reference the form html looks like such:
<%= simple_form_for#product do |f| %>
<h1 class="heading">Edit Product</h1>
<%= render 'form', product: #product %>
<% end %>
Any help I can get would be appreciated.
When you use the respond_to do |format| method, you need to supply the actual formats that the code should respond to. So, your controller probably needs to look something like this:
def create
#product = Product.new(product_params)
#product.user_id = current_user.id
respond_to do |format|
format.html do
if #product.save
...
end
end
end
But I'd also ask: why are you using respond_to here if you only expect to process the result of a web form? It's something you may need to do at some point, but isn't required initially and adds complication.
If that doesn't resolve the issue, we'll probably need to see your strong-params function (product_params), the Product model definition and your view, at least. For example, you may need to structure the line more like this, because your params may well not exactly match the fields in your model.
#product = Product.new(id: product_params[:id], name: product_params[:name])
Rails adds a special authentication code when it creates a form, to help stop bad actors from spamming or hacking your form. If your page is changed after the code is created, it will become out of date and be rejected, but I'd expect a more specific error if that was happening. Fingers crossed!
I am struggling to get this working. I have three models
Student
Classroomattnd
Classroom
Using the has_many :through relationship. All my relationships are defined correctly and I have setup the nested form using the accepts_nested_attributes.
So when creating a new student I want to select from a list of classrooms instead of creating a new classroom. The form part also works fine the part I am not getting is when I create the student it complains about the following error.
Couldn't find Classrooom with ID=3 for Student with ID=
I have searched around for few days now but can not get the answer I need to get this working.
def new
#student = Student.new
#student.classrooms.build
end
def edit
end
def create
#student = Student.new(student_params)
respond_to do |format|
if #student.save
format.html { redirect_to #student, notice: 'Student was successfully created.' }
format.json { render :show, status: :created, location: #student }
else
format.html { render :new }
format.json { render json: #student.errors, status: :unprocessable_entity }
end
end
end
Can someone help here, someone must of face this issue before?
Also in the rails console when I run the following it works:
classroom = Classroom.last
student = Student.create(name: 'Dave', classrooms:[classroom])
Your parameter handling isn't supporting nesting. You can look at request parameters in your server log or inspect the fieldnames of your generated form to be sure of your target. It's going to be something along the lines of
def student_params
params.require(:student).permit(:student => [:name, :classroom => [:id, :name]])
end
Or maybe as below. In this second case I'm not assuming everything in the form is nested under a student container. Also note the switch from classroom to classroom_attributes which is a change I have sometimes needed to make even though the form above is what the docs indicate.
def student_params
params.require(:name).permit(:classroom_attributes => [:id, :name])
end
Hopefully that gives you a notion of how to tailor your parameter definition to what your form is generating. Also note your error messages give you indication of what part of your definition is failing, eg the missing Student id in the error you quote.
I have this custom action which I want to save http trips to retrieve different collections with.
def dashboard
#projects = Project.all
#tasks = Task.all
respond_do do |format|
format.json {render {projects: #project, tasks: #tasks}, serializer: DashboardSerializer }
end
end
class DashboardSerializer < ActiveModel::Serializer
attributes :proejcts, :tasks
end
this gives me an error like this
undefined method `read_attribute_for_serialization' for #<Hash:0x007fb5d58108c0>
Is there any way that I can make arbitrary collection attributes in the active model serializer template as I can do in Rabl?
Thank you!
AMS has a distinction between single item serialization and item collection serialization.
I was getting the same error, my solution looked like this:
render json: #posts, each_serializer: FancyPostSerializer
I have the shop with has_many association and include items to it so that the items belonging to that shop is received
format.json { render json: {:shop => #shops.as_json(:include => :items)}}
now it gives all the items that belongs to that shop but i want to get items with specific condition, say item_type = "accessories". so how can i do this? please help me.
EDIT
I have put a new question in How to get the value of include with conditions?
You should filter the data with ActiveRecord, and then call the as_json on the filtered data.
You can do something like:
#shops = Shop.includes(:items).where("items.itemp_type = ?", 'accesories')
format.json { render json: { :shop => #shops.as_json(:include => :items) } }
One way you could do this is to create a hash with the objects you want to render, and then pass that to the render method. Like so:
respond_to do |format|
format.json { render :json => {:shops => #shops,
:items => #items }}
end
If the models aren't associated through active record, that's probably your best solution.
If an association does exist, you can pass an :include argument to the render call, like so:
respond_to do |format|
format.json { render :json => #shops.to_json(:include => [:items])}
end
Note that you wouldn't have to retrieve the #items variable in the section above if you take this approach, Rails will automatically load it from the #shops variable.
I have a "recipes" table and an "ingredients" table. Each recipe "has_and_belong_to_many" ingredients and each ingredient "has_and_belong_to_many" recipes.
I want to add a link to the ingredient page: "show all recipes which contain this ingredient".
I wrote the following code in my ingredient controller:
def recipes
#ingredient = Ingredient.find(params[:id])
#recipes = #ingredient.recipes
respond_to do |format|
format.html # index.html.erb
format.json { render json: #recipes }
end
end
My problem is that now it expects me to have a "recipes.html.erb" file under the "ingredients" view.
I don't want to create a new view for this, I just want to use the same code I use in the "recipes" view (recipes/index.html.erb).
How can I direct rails to this view?
(I'm using rails 3.x)
Thanks,
Li
Like this:
def recipes
#ingredient = Ingredient.find(params[:id])
#recipes = #ingredient.recipes
respond_to do |format|
format.html { render "recipes/index" }
format.json { render json: #recipes }
end
end
For details, please take a look at the rails guide: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render