Rails Routes with Param - Controller ignoring param - ruby-on-rails

I'm trying to figure out how to do filters for a datatable, so my thought in the interim is to have the an <option> apply a param to the URL, and the basis of the table to change, however, my Controller seems to be ignoring the parameters
def index
#steam_games = SteamGame.all
#steam_games = SteamGame.where("#{params[:genre]} = ANY (genres)") if params[:genre].present?
respond_to do |format|
format.html
format.json { render json: SteamGamesDatatable.new(view_context, #steam_games) }
end
end
Is the best way I can think to apply it.
To test I also added in
get '/steam_games/:genre', to: 'steam_games_controller#index' to the Routes, even though I'd like the URL to not change.
My debugger is showing
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
genre: indie
controller: steam_games
action: index
permitted: false
ON load I see Parameters: {"genre"=>"indie"} in the console.
Why is it that this isn't working? To note the genres is an ARRAY which is why I have the where as such, but that shouldn't change the parameter binding.
(Unsure what else to link reg. this).
It's POSSIBLE Datatables is trumping the index of the Controller, but I don't believe so since I feed it the list.

It seems to me that this is a strong params issue. You need to permit the params be used. You can try something like this in your controller.
def index
#steam_games = SteamGame.all
#steam_games = SteamGame.where("#{steam_game_params[:genre]} = ANY (genres)") if steam_game_params[:genre].present?
respond_to do |format|
format.html
format.json { render json: SteamGamesDatatable.new(view_context, #steam_games) }
end
end
private
def steam_game_params
params.permit(:genre)
end
Here's a link to ActionController::Parameters documentation.

Related

Insert another field into GET response JSON

I have the following code that responds to GET /something.json:
def index
#something = Something.all
respond_to do |format|
format.json { render json: #something }
end
end
That runs a SELECT * FROM something in the database, formats the result into a JSON, and responds with it.
The request might ask for another field through a query parameter, which is in a different table than something. I managed to retrieve the desired field doing this:
def index
#something = Something.all
if params[:get_field_from_some_other_table] == "true"
#something.each do |i|
some_other_table = SomeOtherTable.find(i.some_other_table_id)
the_field_i_want = some_other_table.the_field
end
end
respond_to do |format|
format.json { render json: #something }
end
end
But I haven't found a way to add the field to the JSON string. How can I do that? Or is there a better way to retrieve the field with the contents of the something table through a JOIN or something like that?
something and other_table should be related at active_record somehow... maybe a has_one?
Try that and then just use #something.all.includes(:other_table_attribute)
Apart from that, please post your code properly with some readable examples, that helps a lot and will give you faster responses :)

Render different controller methods as JSON in Rails 5.2

I have a resource that renders as JSON perfectly fine at localhost:3000/gins.json from #gins = Gin.order(name: :desc).
Which will return ALL gins. However, I'd like to have a JSON response that only returns the last 4 gins, to use elsewhere. In the controller I also have:
#latestgins = Gin.order("created_at DESC").first(4)
The above would work in an index.html.erb view with <%= #latestgins.name %>, but how do I get the JSON for this? I have tried render json: #latestgins but navigating to localhost:3000/latestings.json, of course, gives a routing error.
I suspect I'm attacking this in completely the wrong way, but only just starting out with Rails API.
you can add respond to format json in your index method:
def index
#gins = Gin.order(name: :desc)
#latestgins = Gin.order("created_at DESC").first(4)
respond_to do |format|
format.html
format.json { render json: #latestgins }
end
end
your #latestgins is now available here : localhost:3000/gins.json
Edit
If you want a custom route to display your data, just add it in your routes:
defaults format: :json do
get 'last4gins', to: "gins#index"
end
Your data for the last 4 entries is available at http://localhost:3000/last4gins.json, at http://localhost:3000/last4gins but also at localhost:3000/gins.json
If you want to keep the gins index route clean, you can also create a custom method and remove the #latestgins from your index:
# routes
get 'last4gins', to: "gins#last4gins"
#controller
def index
#gins = Gin.order(name: :desc)
end
def last4gins
#latestgins = Gin.order("created_at DESC").first(4)
render json: #latestgins
end
Now the data is no more available at /gins.json

JSON format not displaying all model attributes (Rails 4)

I've run into a bizarre issue running Rails 4.2.7: When I look at the HTML index view for a particular model, everything seems fine. When I request the same data via JSON, I only get a subset of the attributes.
My index action is just:
def index
#coverages = Coverage.all
end
If I call it with
http://localhost:3000/coverages
everything is there. If I call it with
http://localhost:3000/coverages.json
I only get 7 of the attributes returned, in addition to the :id, :created_at, :updated_at, and a :url to the instance (e.g. http://localhost:3005/coverages/1.json).
Is the JSON method somehow truncating the attributes? I never recall running into this before.
POSTSCRIPT:
I modified the index action to:
def index
#coverages = Coverage.all
respond_to do |format|
format.html {render :index}
format.json {render json: #coverages}
end
end
and now I get all the attributes. Probably I was violating Rails best practices by not including the explicit format statements, but I am still curious about my original result.
I'm posting the solution I found (in the Postscript of the question) here in case it is useful. Still an open question as to why the original configuration didn't work.
Modifying the index action to:
def index
#coverages = Coverage.all
respond_to do |format|
format.html {render :index}
format.json {render json: #coverages}
end
end
solves the issue.

Send a variable from one action to another in ruby on rails

Code in controller is
if params["type"] == "user"
respond_to do |format|
format.html { redirect_to home_user_path, notice: "abc" }
end
If I send variable with notice then work fine but I want to send with my own key like
format.html { redirect_to home_user_path, search: "abc" }
It doesn't recieve there
You must remember that you're not "sending" a variable to another action; you're invoking another action, and populating it with a variable (data):
1. Instance Variable
You can set an instance variable, which will then be available in the next action:
def your_action
#search = "abc"
respond_to do |format|
format.html { redirect_to home_user_path } #-> #search will be available in the other view
end
end
2. Sessions
You're currently trying to use sessions to populate the data:
def your_action
redirect_to home_user_path, search: "abc"
end
#app/views/controller/your_action.html.erb
<%= flash[:search] %>
3. URL
Finally, you can set the value in the URL through your routes:
def your_action
redirect_to home_user_path(search: "abc") #-> you'll probably need to set the user object too, judging from the route name
end
This should populate your route with some GET request params: url.com/action?param=value
The underpin of all of this, as mentioned, is that you're not sending a variable, you'll be initializing it in your current controller action, and then having the next action call it.
This is a problem with Ruby's optional braces: sometimes it's hard to see which method call something is being treated as an argument to.
Try this instead:
format.html { redirect_to home_user_path(search: "abc") }
this will redirect to home_user_path and set params[:search] to "abc".

Call Rails Model function from Controller

I'm new to Rails, and am trying to make a pet app. It has 3 attributes: name, hungry, and mood. I generated a scaffold and wrote a feed method into the model:
def feed
self.hungry==false;
save!
end
I want feed to be something a user can do in the edit view, so I created a checkbox to indicate feeding vs. not feeding. My plan was to call the feed function from the controller in the update function. Right now, it looks like this:
def update
respond_to do |format|
if #pet.update(pet_params)
format.html { redirect_to #pet, notice: 'Pet was successfully updated. #{params[:feed]}' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #pet.errors, status: :unprocessable_entity }
end
end
if #pet.update_attributes(params[:feed])
#pet.feed
end
end
I have an odd sense that I'm mixing metaphors here, but am not sure of the right course of action. I'm trying to call a function from my update function, and that doesn't seem to be working. It might have to do with the fact that "feed" isn't listed in my model's parameters, but I don't need it to be. I just need it to call a function. Help!
Your method definition is wrong. Instead of assigning a value, you are comparing equality.
def feed
self.hungry == false; # only one = should be used.
save!
end
There is a better way to do this, however:
class Pet
attr_accessor :feed_me
before_save :feed
def feed
hungry = false if feed_me
end
end
You should not need the controller check:
if #pet.update_attributes(params[:feed])
#pet.feed
end
Which is wrong, by the way. You need to check if the param[:feed] exists, not if the pet objet has updated correctly.
For this solution to work, you would need to add an attribute to your form:
= f.check_box :feed_me
Another way to do this would be to map the hungry attribute to the checkbox and just name the label feed:
= f.label :hungry, "Feed"
= f.checkbox :hungry
You could then go ahead and just remove the before_save, the attr_accessor, and the method self.feed.

Resources