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 :)
Related
To start out I have already looked at this thread and this thread.
I have a piece of code that has a couple different postgres calls, and then appends on another model collection named Category within our response. I want to filter out certain pieces of response depending on a search param passed in by the json. My current code is here:
def clues
....
clues = clues.where("category_id = ?", params[:category]) if params[:category].present?
offset = params[:offset].present? ? params[:offset] : 0
#result = clues.limit(100).offset(offset)
respond_to do |format|
if(!params[:category_keyword])
format.json { render :json => #result.to_json(:include => :category) }
else
format.json { render :json => #result.to_json(:include => Category.where("title LIKE ?", '%' + params[:category_keyword] + '%')) }
end
end
end
Right now, the end if statement in the respond_to do is broken, as I don't think my :include for the else statement is in a correct format to filter out, as it just doesn't append the nested model to my json response. What is the best way to filter out these nested calls?
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.
I have a simple index action in my controller that serves html and json formats.
def index
#records = Model.all
respond_to do |format|
format.html
format.json { render json: #records }
end
end
I've recently redone the HTML view in AngularJS backed by the JSON endpoint. I've noticed from the logs that when loading the HTML for this action that the query is still being made for the HTML view even though I've setup AngularJS to fetch the records at the JSON endpoint on load.
I'm not sure of the best way to handle this. I'd like to be able to not query if I'm just responding to HTML. The obvious way would be to only run the query if the format is JSON, but I have a feeling that's not the best way.
You can solve that simply by doing
def index
respond_to do |format|
format.html
format.json {
#records = Model.all
render json: #records
}
end
end
In Rails 3, calling all on a Model hits the database and retrieve the result.
In Rails 3 Model.all.class = Array[Class] of activerecord objects.
If you want your query to be run only when you iterate over the collection in your view don't call .all directly on your Model class. You can do something like:
#records = Model.scoped
and in your view, when you need to display your collection:
<% #records.each do |record| %>
<%= record.inspect %>
<% end %>
In Rails 4, all returns an ActiveRecord_Relation object and not hits the database until you iterate over your collection.
More info at: http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-all
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.
I'd like to be able to obfuscate the id's of objects in my app so that a URL can be shared, but not easily guessed.
I've gathered that I need to store a hashed_id in the database for the object, and that it may be possible to rewrite the to_param function to use that hashed_idin the URL but I'm having trouble getting it to work.
model:
after_create :create_hashed_id
def to_param
self.hashed_id
end
def create_hashed_id
self.update_attributes(:hashed_id => Digest::SHA1.hexdigest([Time.now, rand].join)[0,16])
end
controller:
def show
#upload = Upload.find_by_hashed_id(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #upload }
end
end
The object gets created with a hash_id attribute but when I try and invoke the show method it looks like it's looking in the id column instead of the hashed_id column.