Reputation: 889
I am trying to get a drop down data from a route.
I made the dropdown data a model.
create_table "choices", force: :cascade do |t|
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
and I seed it as following:
Choice.create!(
[
{
description: "Choice 1"
},
{
description: "Choice 2"
}
]
)
This drop down model does not have its own controller, it is used by another model's api controller. The model looks like
create_table "forms", force: :cascade do |t|
t.text "username"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
And this is how "Choice" Model is used in the form's controller
class Api::FormsController < ApplicationController
def choices
all_choices = Choice.all.
map {|e| {"label" => e.description, "value" => e.id}}.as_json
respond_to do |format|
format.json { render json: all_choices, status: :ok }
end
end
end
I also create a get route for that model
constraints(lambda { |req| req.format.symbol.in? [:json, :csv, :xlsx] }) do
post '/login' => 'sessions#create'
namespace :api, defaults: { format: :json } do
get '/forms/choices' => 'forms#choices'
end
end
and from my front-end(Using React)
getDropdown(){
ajax({
url: `/api/forms/choices.json`,
dataType: 'json',
success: data => {
this.setState({
choices: data
});
},
error: () => {
console.log("Error retrieving data")
}
})
}
When I use console.log(this.state.choices)
to print out the data I got, I got empty object. I am relatively new to rails and understand that it is convention over configuration, so I believe I am missing something small here.
Any help is appreciated.
Upvotes: 0
Views: 84
Reputation: 2483
The explanation is simple. You have the following route:
get '/forms/:user_id' => 'forms#show'
So, it will match:
/api/forms/1
/api/forms/2
But it also matches:
/api/forms/otherstuff
/api/forms/some_string
/api/forms/choices
In general, you should read your route as:
match /api/forms
and then, if there is anything else added to the route, treat it as a :user_id
.
This is described in the Rails documentation:
Rails routes are matched in the order they are specified, so if you have a resources :photos above a get 'photos/poll' the show action's route for the resources line will be matched before the get line. To fix this, move the get line above the resources line so that it is matched first.
Source: http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
Upvotes: 1
Reputation: 889
The problem is my route. There are other routes before the choice
route in fact.
constraints(lambda { |req| req.format.symbol.in? [:json, :csv, :xlsx] }) do
post '/login' => 'sessions#create'
namespace :api, defaults: { format: :json } do
get '/forms/otherstuff' => 'forms#otherstuff'
get '/forms/:user_id' => 'forms#show' <----
get '/forms/choices' => 'forms#choices' <----
end
end
I fixed it by switching the choice
route with the route above it, just simply switched their places and it worked.
constraints(lambda { |req| req.format.symbol.in? [:json, :csv, :xlsx] }) do
post '/login' => 'sessions#create'
namespace :api, defaults: { format: :json } do
get '/forms/otherstuff' => 'forms#otherstuff'
get '/forms/choices' => 'forms#choices' <----
get '/forms/:user_id' => 'forms#show' <----
end
end
I have no idea why, I would love to get a explanation of this rail behavior
Upvotes: 0