Rails - Combining scopes - ruby-on-rails

Here is the index method of my People Controller
def index
#people_without_pagination = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
#people = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
.page params[:page]
if(params[:my_contacts]=="true")
#people.my_contacts(current_user.id)
#people_without_pagination.my_contacts(current_user.id)
end
get_facets
#organization = Organization.find(session[:organization_id])
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: #facets}}
format.csv { send_data #people_without_pagination.to_csv}
end
end
As you can see, the my_contacts scope is only to be used when the param "my_contacts" is set to true.
However, it never seems to be applied when I split the scopes. When I combine the my_contacts scope with the rest, it works perfectly. Code here :
def index
#people_without_pagination = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
.my_contacts(current_user.id)
#people = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
.page(params[:page])
.my_contacts(current_user.id)
get_facets
#organization = Organization.find(session[:organization_id])
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: #facets}}
format.csv { send_data #people_without_pagination.to_csv}
end
end
Is this not an acceptable way of combining scopes?

Each time you call the relation builder methods (where, joins, etc.) or your model's scopes you create a fresh new scope - it doesn't mutate the existing scope. So
#people.my_contacts(current_user.id)
Creates a new scope but then throws it away, leaving #people unchanged. You should be doing
#people = #people.my_contacts(current_user.id)
This also means that your code could be simpler:
#people_without_pagination = Person.
... #your scopes here
#people = #people_without_pagination.page(params[:page])
rather than repeating that list of scopes.

Related

How to render view in parent controller

I want to pass down values from a parent controller, to the views of the child, or ideally, render the view directly from the parent controller.
Here is my parent controller:
class SuperBlogPostsController < ApplicationController
def index(country)
if country == "AUSTRALIA"
#posts = AustraliaBlogPost.all
hash = { posts: #posts, featured_post: AustraliaBlogPost.find_by(featured_post: true) }
respond_to do |format|
format.html {render 'super_blog_post/index'}
format.json {render json: hash}
end
end
end
def show(country)
if country == "AUSTRALIA"
#post = AustraliaBlogPost.find(params[:id])
respond_to do |format|
format.html {render 'super_blog_post/show'}
format.json {render json: #post}
end
end
end
And here is my child:
class AustraliaBlogPostsController < SuperBlogPostsController
def index
super(country: 'AUSTRALIA')
end
def show
super(country: 'AUSTRALIA')
end
end
This is the error that I get, even when I append .json at the end of the url:
Is it possible to do the rendering of the view in the parent, or at least pass down the return values of the variables generated by the parent to the child? If I've been unclear at all, let me know!
Thanks!
Your parent controller methods accept a normal parameter, not named parameter.
Instead of:
super(country: 'AUSTRALIA')
You need
super('AUSTRALIA')
But I must say, the entire logic of your controllers doesn't make a lot of sense.

How do I create an instance variable in rails using OpenStruct

I would like to return facets along with the data in my controller. My code was :
def index
#people = Person.for_branch(session[:branch_id]).for_interests(params[:interest_search]).search_query(params[:search_term]).for_lead_sources(params[:lead_source_search]).page params[:page]
#organization = Organization.find(session[:organization_id])
#facets.total_count = Person.all.count
#facets.filtered_count = #people.count
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: #facets}}
end
end
However, I keep getting the error total_count is not defined.
undefined method `total_count=' for nil:NilClass
How can I fixed this?
I think you want to use OpenStruct variable.
require 'ostruct'
# ...
def index
#people = Person.for_branch(session[:branch_id]).for_interests(params[:interest_search]).search_query(params[:search_term]).for_lead_sources(params[:lead_source_search]).page params[:page]
#organization = Organization.find(session[:organization_id])
#facets = OpenStruct.new # initializing OpenStruct instance
#facets.total_count = Person.all.count
#facets.filtered_count = #people.count
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: #facets}}
end
end
Please note, that it is more convinient to use plain old Hash instead:
facets = {total_count: Person.all.count, filtered_count: #people.count}
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: facets}}
end
and use it in your views like this:
total count is <%= facets[:total_count] %>

Rails - How to render json with extra field in index controller method

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.

Render custom json polymorphic list

I have a /tags.json where i want to render a list of players and teams, using the following which i have put in both players and teams model.
def token
"#{id}_#{self.class.name}"
end
Tags controller
def index
#players = Player.all
#teams = Team.all
#tags = #teams + #players
respond_to do |format|
format.json { render json: #tags}
end
end
But how can i create a list in my tags controller, so i can get something like this
[
{"name":"Bob","token":"1_Player"},
{"name":"Yankees","token":"1_Team"}
]
How can i do this?
Edit
format.json { render json: #tags.as_json(only: [:name])}
renders
[
{"name":"Bob"},
{"name":"Yankees"}
]
But how could i get token?
Try something like this:
#tags = []
Team.all.each do |team|
#tags.push({name: team.name, tag: team.token})
end
Player.all.each do |player|
#tags.push({name: player.name, tag: player.token})
end
respond_to do |format|
format.json { render json: #tags}
end

How do I give a user access to show their own content OR public content in Rails?

Here is my current controller:
def show
#lesson = #current_user.lessons.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #lesson }
end
end
Currently users can only access their own lessons. If they go to example.com/lessons/[other person's public lesson id] then it doesn't show.
I would like to give users access to show their own lessons or other people's lessons if the lesson table's column public is true in the other person's lesson. How can I do that?
This seems to be working:
def show
begin
#lesson = #current_user.lessons.find(params[:id])
rescue ActiveRecord::RecordNotFound
#lesson = Lesson.where("public = ? AND id = ?", true, (params[:id]))[0]
end
respond_to do |format|
format.html # show.html.erb
format.json { render json: #lesson }
end
end
Is there anything unsafe or unsustainable about this?

Resources