Map field value in ruby - ruby-on-rails

I have such class-array:
#types = Type.where("TYP_MOD_ID = ?", params[:mod_id])
There are i have field TYP_KV_FUEL_DES_ID which is number....
But how can i via map method change this value via method?
I have tried something like:
def get_types_for_mod2
#types = Type.where("TYP_MOD_ID = ?", params[:mod_id])
#types.map { |e| e.TYP_KV_FUEL_DES_ID = get_via_designation(e.TYP_KV_FUEL_DES_ID) }
respond_to do |format|
format.json { render :json => #types}
end
end
def get_via_designation(id)
designation = Designation.find_by_DES_ID(id)
destext = DesText.find_by_TEX_ID(designation.DES_TEX_ID)
destext.TEX_TEXT
end
So how can i change value of e.TYP_KV_FUEL_DES_ID ?
upd1:
i don't need to commit anything! just for json i fetch data and change for view some field! no db!

#types = Type.where("TYP_MOD_ID = ?", params[:mod_id]).map do |type|
type.TYP_KV_FUEL_DES_ID = get_via_designation(type.TYP_KV_FUEL_DES_ID)
type
end
here we will map over the result from the query Type.where("TYP_MOD_ID = ?", params[:mod_id]) and set the TYP_KV_FUEL_DES_ID to the return from get_via_designation
UPDATE: added that the map block will return "type"

Related

How to filter index for true value in Rails 4

I am trying to filter database index list by whether or not a value is true. Is this possible? Within the controller I am attempting this, which is not resolving to an error, but does not pull the index list I am looking for.
Controller:
def index
#people = Person.all
if params[:filter_by]
#people = Person.where(:position => params[:filter_by])
elsif
#people = Person.where(:ra_cs, params[:filter_by] == "true")
else
#people = Person.all
end
end
def person_params
params.require(:person).permit(
:fname, :lname, :user_name, :position, :title, :prefix, :focus1, :focus2, :focus3, :ra_cs, :ra_hn, :ra_mg, :ra_nb, :ra_ne)
end
The entry for the database is a checkbox, which inputs a value of 1 or 0 into the field.
I am not sure what other code might be involved, please let me know if I need to add anything else.
You need to refactor your code:
def index
if params[:filter_by].present?
case params[:filter_by]
when 'ra_cs'
#people = Person.where(ra_cs: true)
when 'ra_aa'
#people = Person.where(ra_aa: true)
when 'ra_bb'
#people = Person.where(ra_bb: true)
else
#people = Person.where(position: params[:filter_by])
end
else
#people = Person.all
end
end
Btw, elsif needs a condition.
Another option is using dynamic where where parameters.
def index
#people = Person.all
#people = #people.where(params[:filter_by] => true) if params[:filter_by].present?
end
If you don't what the user filtering by every attribute you could add a whitelist.
def index
#people = Person.all
allowed = %w[ra_cs ra_aa ra_bb ...]
#people = #people.where(params[:filter_by] => true) if params[:filter_by].in?(allowed)
end
In this second example you don't have to check for the presence, since nil or "" would be returned, which is not in allowed. Meaning that the if-statement would evaluate to false anyway.

How to render a dependency(project.tasks) in a two model (project + task) json result?

Given that each project has_many :tasks, I hope to render the project.task within the json result.
However, the json output also include a list of individual tasks as part of the result. See below:
#tasks = Task.all.reject do |i|
i.project.inbox == false || i.completion_status == 100
end
#projects = Project.all.reverse.reject do |i|
i.inbox == true || i.completion_status == 100
end
#all = #tasks + #projects
respond_to do |format|
format.html
format.json { paginate json: #all.sort_by(&:created_at).reverse,
per_page: 25 }
end
This means that if I simply include:
respond_to do |format|
format.html
format.json { paginate json: #all.sort_by(&:created_at).reverse,
:include => [:tasks => {:only => :id}],
per_page: 25 }
end
Rails will throw an error of undefined method tasks for Task:0x007fa0ad8d3858 since tasks does not have a task method.
How can I have the project.tasks appear in a json result which also include individual tasks result? Thank you.
Consider using active_model_serializers gem. After installing you can define a serializer for Project model like so:
class ProjectSerializer < ActiveModel::Serializer
attributes :id, :created_at, :tasks
def tasks
object.tasks.map(&:id)
end
end
Note: There might be any attributes you need. It's just an example.
Then you can do:
#projects = Project.all.reverse.reject do |i|
i.inbox == true || i.completion_status == 100
end
serialized_projects = ActiveModelSerializers::SerializableResource.new(#projects, each_serializer: ProjectSerializer).as_json
It will return you an array:
[{:id => 1, :created_at => "2017-07-13 08:13:20", tasks => [1, 2, 3, ...]}, ...]
Then for json response you can concat #tasks and serialized_projects:
all_for_json = #tasks + serialized_projects
And finally you can sort it like this:
all_for_json.sort_by { |record| record[:created_at] }.reverse
Note that you should do exactly record[:created_at], because projects are hashes, not active record models.
But I don't think this is a good idea to mix hashes and active record models in one array. So there is another solution.
You can also define a serializer for Task model:
class TaskSerializer < ActiveModel::Serializer
attributes :id, :created_at
end
Note: There might be any attributes you need. It's just an example.
And override code like this:
#tasks = Task.all.reject do |i|
i.project.inbox == false || i.completion_status == 100
end
#projects = Project.all.reverse.reject do |i|
i.inbox == true || i.completion_status == 100
end
respond_to do |format|
format.html do
#all = #tasks + #projects
end
format.json do
serialized_tasks = ActiveModelSerializers::SerializableResource.new(#tasks, each_serializer: TaskSerializer).as_json
serialized_projects = ActiveModelSerializers::SerializableResource.new(#projects, each_serializer: ProjectSerializer).as_json
all_serialized = serialized_tasks + serialized_projects
paginate json: all_serialized.sort_by { |record| record[:created_at] }.reverse, per_page: 25
end
end
To DRY your code, you can put
ActiveModelSerializers::SerializableResource.new(...).as_json
to separate method. For example:
def serialize_collection(collection, each_serializer)
ActiveModelSerializers::SerializableResource.new(collection, each_serializer: each_serializer).as_json
end
And do serializations like this:
serialized_tasks = serialize_collection(#tasks, TaskSerializer)
serialized_projects = serialize_collection(#projects, ProjectSerializer)
Profits of this solution:
You don't mix active record models and hashes in one array.
You can easily define via serializers which attributes and associations to include and set custom names for them.

Ruby on Rails filter array using three fields

I am trying to search through my model using 3 columns. Also if the column is empty, it is valid. This is how I am doing it
def getactivityfortoday
#temp = params[:temp]
logger.debug "params temp:#{#temp.inspect}"
#sky = params[:sky]
#day = params[:day]
#todaysactivities = []
#activities=[]
#finaldata = []
#activities = Weatherclockactivity.all
#attemptactivities = []
#attemptactivities = #user.attempts
for activity in #activities do
logger.debug "activity: #{activity.attributes.inspect}"
if #temp.to_i < activity.temperatureMax.to_i && #temp.to_i > activity.temperatuureMin.to_i
if #sky == activity.sky || activity.sky == ""
if #day == activity.day
#todaysactivities << activity
end
end
end
end
for activity in #todaysactivities
for attempt in #attemptactivities
if attempt == activity
finaldata << {activity: activity, attempt: "yes"}
else
finaldata << {activity: activity, attempt: "no"}
end
end
end
respond_to do |format|
format.html { render action: "new" }
format.json { render json: #finaldata }
end
The response I get is an empty array but I should be getting 3 rows as a response.
spelling mistake here
activity.temperatuureMin.to_i
And
finaldata << {activity: activity, attempt: "yes"}
should be
#finaldata << {activity: activity, attempt: "yes"}
Also you could be more concise
def getactivityfortoday
#temp = params[:temp]
logger.debug "params temp:#{#temp.inspect}"
#sky = params[:sky]
#day = params[:day]
#activities = Weatherclockactivity.all
#attemptactivities = #user.attempts
#finaldata = #activities.map do |activity|
if (activity.temperatureMin.to_i + 1...activity.temperatureMax.to_i).include?(#temp.to_i) && ( #sky == activity.sky || activity.sky == "") && #day
#attemptactivities.include?(activity) ? {activity: activity, attempt: "yes"} : {activity: activity, attempt: "no"}
end
end.compact
respond_to do |format|
format.html { render action: "new" }
format.json { render json: #finaldata }
end
end
How about something like this?
I tried to make it a balance of readability and conciseness. First we filter for the desired activities. Then we structure the output. This should be easier to debug.
def getactivityfortoday
#temp = params[:temp].to_i
#sky = params[:sky]
#day = params[:day]
#activities = Weatherclockactivity.all
#attemptactivities = #user.attempts
selected_activities = #activities.select do |activity|
# Make sure it's the right temperaure
return false unless (activity.temperatureMin.to_i + 1 ... activity.temperatureMax.to_i).include? #temp
# Make sure the sky matches, or the sky is blank
return false unless (#sky.blank? || #sky.activity == activity.sky)
# Make sure the day matches
return false unless #day == activity.day
# Otherwise, it's good!
return true
end
selected_attempted_activities = selected_activities.map do|activity|
ret = {activity: activity}
ret[:attempt] = #attemptactivities.include?(activity) ? "yes" : "no"
ret
end
respond_to do |format|
format.html { render action: "new" }
format.json { render json: selected_attempted_activities }
end
end
There are a few typos in your original (for instance, #finaldata not finaldata). Make sure that you spell instance variables (things starting with #, like #sky) correctly, since if you try to access an undefined instance variable, it'll silently default to nil.
The best and flexible way is to use ActiveModel::Model
It allows you to use many more useful methods.
it will seems like:
app/models/activity_report.rb
Class ActivityReport
include ActiveModel::Model
attr_accessor :day, :activity # and etc.
validates :day, presence: true
def day
#day.to_s # for example
end
def day=(value)
#day = value - 1.month # for example every date which user set will set on one month ago
end
# and etc
end
app/controllers/posts_controller.rb
...
def index
#activity = ActivityReport.new(params[:activity])
end
def create
#activity.create!
end
...
app/views/posts/index.html.haml
= form_for #activity do |f|
= f.day
For more information you could take a look at:
http://edgeapi.rubyonrails.org/classes/ActiveModel/Model.html
http://railscasts.com/episodes/219-active-model (old)
http://railscasts.com/episodes/416-form-objects (newer, but a little complex)

Rails:sorting from controller doesn't work

I want to sort array from controller, that doesn't works, but throws no errors.
def my_published
#tests=Test.where(:user_id => current_user.id, :state=>'saved')
#tests=#tests.sort { |p1, p2| p1.rating <=> p2.rating }
respond_to do |format|
format.html
format.js{#tests}
end
end
Rating is an integer.
P.S. To display array I use each method.
Try this construction:
#test = Test.where(:user_id=>current_user.id, :state=>'saved').order('rating')
You can add the direction of order:
order('rating DESC') or order('rating ASC')

Rails easyist way to create hash with certain attributes and also nested

In my controller I have:
def search
#sog = Konkurrencer.where("titel like ?", "%#{params[:q]}%")
#kate = []
#sog.each do |kat|
h = {}
kat.attributes.each{|k,v| h[k] = v.respond_to?(:force_encoding) ? v.dup.force_encoding("UTF-8") : v }
#kate << h
end
respond_to do |format|
format.html
format.json { render :json => #kate }
end
The problem is that the JSON contains all the attributes for the model. How do I create a JSON that have only ID, url and titel?
The JSON should also contain the key "url" which key should be the URL for the associated photo. I use paperclip. The path is: #konkurrencer.photo.image.url
UPDATE:
My search.json.erb:
[
<% #sog.each do |kon| %>
{"id":"<%= kon.id %>","titel":"<%= kon.titel %>"},
<% end %>
]
How do I remove the , for the last loop?
Create an array with the list of attributes you want to display. Use select query method to get only this fields in the SQL request. And finally loop on this attributes to fill the JSON array:
def search
displayed_attributes = %w{id url titel}
#sog = Konkurrencer.select(displayed_attributes.join(',')).where("titel like ?", "%#{params[:q]}%")
#kate = []
#sog.each do |kat|
h = {}
displayed_attributes.each do |attribute|
v = kat[attribute]
h[attribute] = v.respond_to?(:force_encoding) ? v.dup.force_encoding("UTF-8") : v
end
#kate << h
end
respond_to do |format|
format.html
format.json { render :json => #kate }
end
end

Resources