If I do something like:
result = Appointment.find( :all, :include => :staff )
logger.debug { result.inspect }
then it only prints out the Appointment data, and not the associated staff data.
If I do result[0].staff.inpsect then I get the staff data of course.
The problem is I want to return this to AJAX as JSON, including the staff rows. How do I force it to include the staff rows, or do I have to loop through and create something manually?
:include is an argument for to_json, not find. What you need to do in your controller is this:
def return_json
#appointment = Appointment.find(:all)
respond_to { |format|
format.json { render :json => #appointment.to_json(:include => :staff) }
}
end
You need to setup an association between Appointment and Staff for this to work.
Check out ActiveRecord::Serialization and ActionController::Base (see section: "Rendering JSON")
def show
#appointment = Appointment.find(:all, :include => :staff)
respond_to do |format|
format.html
format.js { render :json => #appointment.to_json(:methods => [:staff]) }
end
end
Related
I'm using Rails 4.0.2 with paperclip for image upload in my project. Also I need to send a full image path of paperclip. So I can do it with add new field and set image path manually in my show controller method for particular record.
show
def show
respond_to do |format|
format.html
format.json { :json => JSON::parse(#demo.to_json.merge("new_field" => #demo.image_url.url).to_json}
end
end
When I view Json for any of my record, this is will showing good.
{
id: "1",
name: "demo",
new_field: "/demo/1/original/file.jpg"
}
In same scenario, I need to get the full image path of paperclip image for all records when I am requesting to index method on controller
index
def index
#demos = Demo.all
respond_to do |format|
format.html
format.json { :json => Demo.all.to_json}
end
end
I tried some of codes, but I don't know how exactly to write
def index
#demos = Demo.all
#demos.each do |demo|
new_field = {"new_field" => #demo.image_url.url}
# After I stucked with logic, how to uppend with 'demo'.
end
respond_to do |format|
format.html
format.json { :json => Demo.all.to_json}
end
end
How do I iterate my individual Demo model and How to merge full image path into each record.
I found the solution for my question,
def index
#demos = Demo.all
#demos_data = []
#demos.each do |demo|
new_field = {"new_field" => #demo.new_field.url}
demo = JSON::parse(demo.to_json).merge(new_field)
#demos_data << demo
end
respond_to do |format|
format.html
format.json { :json => #demos_data}
end
end
I suggest you to use two approaches, 1)use active model serializer to expose json response. 2) use jbuilder library to expose custom fields. Still you need help please let me know.
Try this:-
def index
#demos = Demo.all
#demos_data = []
#demos.each do |demo|
demo["new_field"] = #demo.image_url.url
#demos_data << demo
end
respond_to do |format|
format.html
format.json { :json => #demos_data}
end
end
maybe you can try:
def index
#demos = Demo.all
#demos.map do |demo|
new_field = {"new_field" => #demo.image_url.url}
demo.attributes.merge(new_field)
end
respond_to do |format|
format.html
format.json { :json => #demos}
end
end
attributes method returns a hash of all the object attributes, just need merge new key-value into the returned hash.
Another way of doing it is in your controller where you are rendering the json
render json: #merchants,
include: {
offers: {
except: [:created_at, :updated_at],
include: {
categories: {
except: [:created_at, :updated_at]
}
}
},
location: {
methods: :country_name,
except: [:created_at, :updated_at]
}
},
except: [:created_at, :updated_at]
Note the methods: :country_name, there you can render methods from your model as json attributes. and through include: ... you can eager load and render related models.
My event model has this method to override the json view for fullcalender.
def as_json(options = {})
{
:id => self.id,
:title => self.title,
:slug => self.slug,
:description => self.description || "",
:start => starts_at.rfc822,
:end => ends_at.rfc822,
:allDay => self.all_day,
:recurring => false,
:url => Rails.application.routes.url_helpers.event_path(id)
}
end
My relationships are:
class Event
belongs_to: city
end
class City
belongs_to: region
has_many: events
end
class Region
has_many: cities
end
Contoller
def index
#region = Region.find(1)
#cities = #region.cities
# full_calendar will hit the index method with query parameters
# 'start' and 'end' in order to filter the results for the
# appropriate month/week/day. It should be possiblt to change
# this to be starts_at and ends_at to match rails conventions.
# I'll eventually do that to make the demo a little cleaner.
#events = Event.scoped
#events = #events.after(params['start']) if (params['start'])
#events = #events.before(params['end']) if (params['end'])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #events }
format.js { render :json => #events }
end
end
# GET /events/1
# GET /events/1.xml
def show
#event = Event.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #event }
format.js { render :json => #event.to_json }
end
end
The correct url/path is a nested resources (region_city_event). How can I grab the region and city value and place them in the :url so the url is correct and nested?
Okay, so since the index action is where you are responding with the json of events, you need to use the same link helper in the javascript code that you use to link users to the index html page.
In your view, you can just have something like this:
<script>
var calendar_url = '<%= regions_cities_events_path(#region, #city) %>'
</script>
You'll need to add the following line to your index action in the events controller:
#city = City.find params[:city_id]
If I understood you well you want to map '/region/city/event_id' to your events controller show action - to do that add this route to routes.rb:
match '/:region_id/:city_id/:event_id' => 'events#show'
Then in your show method in EventsController you can use params[:region_id] and params[:city_id] to find the region and city the user was looking for.
In my controller I have:
#pakkes = Pakke.where("navn like ?", "%#{params[:q]}%")
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #pakkes }
format.json { render :json => #pakkes.map(&:attributes) }
end
How do I change the attribute navn to name when rendering JSON?
You can do this with a one-line method in Pakke:
def as_json(*args)
super.tap { |hash| hash["name"] = hash.delete "navn" }
end
Calling super will generate json hash as usual, then before it's returned you'll swoop in and change the key of the "navn" entry.
Override the as_json method. It's used by to_json in order to produce the output. You can do something like:
def as_json options={}
{
name: navn,
.... # other attributes you want to add to json
}
end
I am trying to change all of the default_standing fields to FALSE for all other records when someone marks one as TRUE. That way I will only ever have one default record in the table. Here is what I am doing in both create and update in my controller, but it doesn't seem to be working:
def update
#standing = Standing.find(params[:id])
if #standing.default_standing
#standings = Standing.where(["default_standing = ? AND id != ?", true, params[:id]])
#standings.each do |s|
s.default_standing = false
s.save!
end
end
respond_to do |format|
if #standing.update_attributes(params[:standing])
format.html { redirect_to(#standing, :notice => 'Standing was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #standing.errors, :status => :unprocessable_entity }
end
end
end
I think the condition is wrong in shingara's update_all.
Should update all where id is not standing.id:
class Standing
def self.all_false_instead_of(standing)
return if standing.default_standing
Standing.update_all(["default_standing = ?", false], ['id <> ?', standing.id])
standing.update_attributes!(:default_standing, true)
end
end
class Standing
def self.all_false_instead_of(standing)
return if standing.default_standing
Standing.update_all("default_standing = false", {:id => standing.id})
standing.update_attributes!(:default_standing, true)
end
end
It's better in Model and something like that I suppose. Have you the unit test failing ?
In your controller
def update
#standing = Standing.find(params[:id])
Standing.all_false_instead_of(#standing)
end
In your code you never push default_standing to true in you #standing
I have a nested form with the following models:
class Incident < ActiveRecord::Base
has_many :incident_notes
belongs_to :customer
belongs_to :user
has_one :incident_status
accepts_nested_attributes_for :incident_notes, :allow_destroy => false
end
class IncidentNote < ActiveRecord::Base
belongs_to :incident
belongs_to :user
end
Here is the controller for creating a new Incident.
def new
#incident = Incident.new
#users = #customer.users
#statuses = IncidentStatus.find(:all)
#incident.incident_notes.build(:user_id => current_user.id)
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #incident }
end
end
def create
#incident = #customer.incidents.build(params[:incident])
#incident.incident_notes.build(:user_id => current_user.id)
respond_to do |format|
if #incident.save
flash[:notice] = 'Incident was successfully created.'
format.html { redirect_to(#incident) }
format.xml { render :xml => #incident, :status => :created, :location => #incident }
else
format.html { render :action => "new" }
format.xml { render :xml => #incident.errors, :status => :unprocessable_entity }
end
end
end
This all exists in a nested form for an incident. There is a text area for the incident_notes form that is nested in the incident.
So my problem is that the incident_notes entry is submitted twice whenever I create the incident. The first insert statement creates an incident_note entry with the text from the text area, but it doesn't attach the user_id of the user as the foreign key. The second entry does not contain the text, but it has the user_id.
I thought I could do this with:
#incident.incident_notes.build(:user_id => current_user.id)
but that does not appear to work the way I want. How can I attach the user_id to incident_note?
Thanks!
I finally figured it out. I needed to do this in the Incident controller:
def create
#incident = #customer.incidents.build(params[:incident])
#incident.incident_notes.first.user = current_user
rather than:
def create
#incident = #customer.incidents.build(params[:incident])
#incident.incident_notes.build(:user_id => current_user.id)
I don't think you need
#incident.incident_notes.build(:user_id => current_user.id)
on new action. You're building the incident_notes twice.