I have 2 models Prize and Staff, One staff HAS_MANY prizes
I want to export noy only the prize, but also embedded the prize's owner (staff) in the JSON response.
How to do it ?
render json: Oj.dump( Prize.where(:staff_id => nil) )
Sample output (But not including the staff information)
{
can_accept_prize_now: true,
name: "Apple MacBook Pro Retina",
sn: 3,
}
Expected output
{
can_accept_prize_now: true,
name: "Apple MacBook Pro Retina",
sn: 3,
staff_id: 80,
staff_name: "Eric"
}
You could probably could add something like the following to the Prize model:
def serializable_hash(options={})
hash = super
hash['staff_id'] = staff.id
hash['staff_name'] = staff.name
hash
end
If you're using ActiveModel::Serializers, you could probably do something like the following
class PrizeSerializer < ActiveModel::Serializer
attributes :can_accept_prize_now, :name, :sn, :staff_id, :staff_name
def staff_id
object.staff.id
end
def staff_name
object.staff.name
end
end
Related
I want to combine similar methods and views into one, but still keep the url name, like the following:
Home/recommends/categories/shopping
Home/recommends/categories/nightview
Home/recommends/categories/food
Home/recommends/categories/area
I don't want to use params like "?something=xyz" in url.
In routes.rb:
resources :recommends, only: :index do
collection do
resources :categories, only: :show, controller: 'recommends' do
collection do
get :food
get :area
get :shopping
get :nightview
end
end
end
end
In controllers:
def food
set_paginator
#recommends = UserRecommend.where(category: "food").order('created_at desc').offset(#offset).limit(#limit).all
#number_of_recommends = UserRecommend.where(category: "food").count
end
def area
set_paginator
#recommends = UserRecommend.where(category: "area").order('created_at desc').offset(#offset).limit(#limit).all
#number_of_recommends = UserRecommend.where(category: "area").count
end
...
In views I have:
food.html.slim
area.html.slim
shopping.slim
nightview.slim
Which are using the same code, just different names in h1:
h1
| Shopping ( or Area or Food... )
= " (#{#number_of_recommends})"
= render partial: "layouts/paginator",
locals: { total_items: #number_of_recommends, per_page: #limit, current_page: #page }
= render partial: "table", locals: { recommends: #recommends }
Can anyone help me refactor this code?
You can (and should) have a single route, a single action, and a single view. The key is to make the variable portion of your URL into an actual variable. You do this using dynamic segments.
First, a single route. There is no need to use resources if you're not actually generating multiple RESTful actions:
get "/recommends/categories/:category" => "categories#show"
You can add criteria on what is allowed for the :category segment:
get "/recommends/categories/:category" => "categories#show", category: /food|area|shopping|nightview/
Next, a single action:
class CategoriesController < ApplicationController
before_action :set_paginator
def show
# params[:category] is "food"/"area"/etc
categories = UserRecommend.where(category: params[:category]).order('created_at desc')
#recommends = categories.offset(#offset).limit(#limit)
#number_of_recommends = categories.count
end
end
Finally, a single view:
# app/views/categories/show.slim
h1
= params[:category].capitalize
= " (#{#number_of_recommends})"
= render partial: "layouts/paginator",
locals: { total_items: #number_of_recommends, per_page: #limit, current_page: #page }
= render partial: "table", locals: { recommends: #recommends }
I would consider it better to use localization to turn the params[:category] into a title, which would give you more control, rather than relying on simple capitalization of the URL segment:
# app/views/categories/show.slim
h1
= t params[:category]
And:
# config/locals/en.yml
en:
categories:
show:
food: 'Food'
area: 'Area'
nightview: 'Night View'
I am getting a pesky ActiveModel::ForbiddenAttributesError, and I can't find how to fix it.
I was following this guide:
https://rbudiharso.wordpress.com/2010/07/07/dynamically-add-and-remove-input-field-in-rails-without-javascript/
and everything works great except when I am updating the record.
My controller:
if params[:add_item]
# rebuild the baixa_itens attributes that doesn't have an id
unless params[:baixa][:baixa_itens_attributes].blank?
for attribute in params[:baixa][:baixa_itens_attributes]
#baixa.baixa_itens.build(attribute.last.except(:_destroy)) unless attribute.last.has_key?(:id)
end
(...)
# Never trust parameters from the scary internet, only allow the white list through.
def baixa_params
params.require(:baixa).permit(:prontuarios_id, :data, :profissional_id, :comentario, baixa_itens_attributes: [ :id, :item_id, :quantidade, :preco, :_destroy ])
end
end
When I got my crash, I tested it in the console:
>> attribute
=> ["1", {"item_id"=>"3", "quantidade"=>"1", "preco"=>"1", "_destroy"=>"0"}]
>> attribute.last.except(:_destroy)
=> {"item_id"=>"3", "quantidade"=>"1", "preco"=>"1"}
>> #baixa.baixa_itens.build(attribute.last.except(:_destroy))
!! #<ActiveModel::ForbiddenAttributesError: ActiveModel::ForbiddenAttributesError>
But if I try to make this build MANUALLY, it works:
>> #baixa.baixa_itens.build({"item_id"=>"3", "quantidade"=>"1", "preco"=>"1"})
=> #<BaixaItem id: nil, baixa_id: 6, item_id: 3, quantidade: 1, preco: #<BigDecimal:7ff97147b6f8,'0.1E1',9(18)>, created_at: nil, updated_at: nil>
>>
What am I missing?
I workaround this problem doing
for attribute in params[:baixa][:baixa_itens_attributes].permit!
in my controler (not using ! would give me error: "Unpermitted parameters: 0, 1", which i cant understand)
I still wish a better solution.
How to add new fields for spree::pre_order in Spree-3.0 + Rails4 ?
Like my old customization: ==========================
app/Controllers/spree/api/pre_order_controller
class PreOrderController < Spree::Api::BaseController
def create
#pre_order = PreOrder.new(pre_order_params)
if #pre_order.save
end
respond_with(#pre_order)
end
private
def pre_order_params
params.require(:pre_order).permit(:user_id,:is_order_created)
end
end
I Got following Error
{
"exception": "param is missing or the value is empty: pre_order"
}
Please let me know your comments.
Say I have a class that has an enum
class Course < ActiveRecord::Base
enum status: { active: 1, in_progress: 2, disabled: 3, ... }
end
and I want to patch the enum functionality so I could do
Course.statuses.capitalize
which would return a list of all statuses - capitalized and without underscores.
I have tried a couple of things but nothing seems to be helping. Any ideas?
Thanks
Below is what I tried. My experience with monkey patching is limited so not really sure if I am on the correct path or not.
module ActiveRecord
module Enum
def capitalize
self.map{ |s| [s[0].capitalize, s[1]] }
end
end
end
I don't see the point of monkey patching this, because what you want already exists in Rails.
class Course < ActiveRecord::Base
enum status: { active: 1, in_progress: 2, disabled: 3 }
end
Course.statuses.transform_keys{|k| k.to_s.humanize}
# => {"Active": 1, "In progress": 2, "Disabled": 3}
I'm getting started with RubyMotion and ProMotion. I'm building a table view and I would like to move the data out into an external file to make it easier to manage. Here's what I have so far:
class MasterScreen < PM::TableScreen
title 'States'
def table_data
[{
title: "Northwest States",
cells: [
{ title: "Oregon", action: :view_details, arguments: { state: #oregon }},
{ title: "Washington", action: :view_details, arguments: { state: #washington }}
]
}]
end
def view_details
open DetailScreen.new(nav_bar: true)
end
end
I'd like to move the names of the states (basically the cell titles) into something like a YAML or JSON file that I can load and iterate over. How can I achieve something like this?
Update: I managed to figure out how to load text from a file.
First I added bubble-wrap to my Gemfile and ran bundle install. BubbleWrap provides the helper method App.resources_path.
In my_app/resources/states.txt I have a list of states, separated by new lines:
Oregon
Washington
Foobar
In my Table View Controller, I read the file and split the file into an array of lines.
class MasterScreen < PM::TableScreen
title 'States'
def on_load
data = File.read("#{App.resources_path}/states.txt")
#states = data.lines
end
def table_data
[{
title: "Northwest States",
cells: #states.map do |state|
{
title: state,
action: :view_details,
arguments: { state: state }
}
end
}]
end
def view_details(arguments)
open DetailScreen.new(nav_bar: true, title: arguments[:state])
end
end
This works, but it's only part of what I was trying to do. I would still like to use a structure like YAML to represent titles and subtitles. What would be the RubyMotion way to do this sort of thing?
Figured out how to do it. I came across a RubyMotion gem called motion-yaml. Simply add it to your Gemfile, add your YAML file to your resources directory, and use it like you would YAML in Ruby.
data = YAML.load(File.read("#{App.resources_path}/my_yaml_file.yml"))
Note: You will need to add bubble-wrap to your Gemfile in order to have the App.resources_path. I'm not sure if there is an easy way to do it without bubble-wrap.