How to permit this parameters:
contacts: [
{:value => 'value', :contacts_type => 'contact_type'},
{:value => 'value', :contacts_type => 'contact_type'},
]
To create many objects by controller action in one JSON request?
Like below, contacts will be an array of resources with specific attributes value and contacts_type:
params.permit(contacts: [:value, :contacts_type])
If you get params like the following:--
:params=>{:xyz => {:contacts => [{:value => 'value', :contacts_type => 'type'}, ..]}}
Then do the folowing:--
params.require(:xyz).permit(contacts: [:value, :contacts_type])
And add attr_accessor :contacts to your model if contacts is just a form field name part.
Work around for this should be
def contact_params
new_params = params.permit(contacts: [:value, :contacts_type])
new_params[:contacts] if new_params
end
Please suggest alternate solution if any
Related
I have searched everywhere but does anyone know if it is possible to permit and array of arrays using strong parameters in rails? My code looks like this:
params.require(:resource).permit(:foo, :bar => [[:baz, :bend]])
This is giving me:
ArgumentError (wrong number of arguments (0 for 1..2))
I have also tried:
params.require(:resource).permit(:foo, :bar => [[]])
params.require(:resource).permit(:foo, :bar => [][])
params.require(:resource).permit(:foo, :bar => [])
But these all give me invalid parameter errors or do not process the parameters.
Thanks in advance for any help
Looking at the code I think this is not possible. you have to flatten the second level.
def permit(*filters)
params = self.class.new
filters.each do |filter|
case filter
when Symbol, String
permitted_scalar_filter(params, filter)
when Hash then
hash_filter(params, filter)
end
end
unpermitted_parameters!(params) if self.class.action_on_unpermitted_parameters
params.permit!
end
Here's an example taken from rails strong parameter Github page:
params.permit(:name, {:emails => []}, :friends => [ :name, { :family => [ :name ], :hobbies => [] }])
I pass a params like this
{
"utf8" => true,
"supply" => {
"items" => { 111 => 112, 89 => 10},
"another_params" => "something"
}
}
My supply_params are:
params.fetch(:supply, {}).permit(:another_params, items: {})
But I get an unpermitted parameters 111 and 89. How can I make items permit all kinds of keys?
This thread in github provides a solution:
def supply_params
params.require(:supply).permit(:another_params).tap do |whitelisted|
whitelisted[:items] = params[:supply][:items] if params[:supply][:items]
end
end
The idea is to explicitly permit any known attributes which are needed and then tack on nested attributes.
According to the #steve klein link to github issue, this is considered as a good solution:
params.permit(:test).tap do |whitelisted|
whitelisted[:more] = params[:more]
end
I have one model which has a foreign key :
class Hotel < ActiveRecord::Base
belongs_to :country
scope :country, lambda { |country_id|
self.scoped.where('country_id IN ( ? )', country_id) unless country_id.blank?
}
end
And in my controller, i do this :
def filter
#hotels = Hotel.scoped
#hotels = #hotels.country(params[:country_id]) unless params[:country_id].blank?
count = #hotels.count
render :json => ['hotels' => #hotels, 'count' => count ]
end
But my json answer has the value country_id but not my contry entity, how can I force that?
Thank you.
You are using "country" as if it were scope, calling it on all Hotels. This isn't correct. I assume you are trying to get all Hotels that belong to country_id. You can do that like this:
#country = Country.find(params[:country_id])
render :json => ['hotels' => #country.hotels, 'country' => #country]
Does that solve your problem? Your question is a little confusing.
I have my answer, I have to use in my controller the :include parameter :
render :json => ['hotels' => #hotels, 'count' => count ], :include=> [:country, :city]
This will add my city and country models to my json answer.
Thank for help !!
I want to use find_or_create_by, but this statement does NOT work. It does not "find" or "create" with the other attributes.
productproperty = ProductProperty.find_or_create_by_product_id(:product_id => product.id, :property_id => property.id, :value => d[descname])
There seems to be very little, or no, information on the use of dynamic finders in Rails 3. "and"-ing these together gives me a an unknown method error.
UPDATE:
Originally I couldn't get the following to work. Please assume I'm not an idiot and "product" is an instance of Product AR model.
product.product_properties.find_or_create_by_property_id_and_value(:property_id => 1, :value => "X")
The error methods was:
no such keys: property_id, value
I couldn't figure that out. Only this morning did I find the reference to passing the values like this instead:
product.product_properties.find_or_create_by_property_id_and_value(1, "X")
And voilá, it works fine. I would have expected a hash to work in the same situation but I guess not.
So I guess you get a down vote if you miss something on the internet?
If you want to search by multiple attributes, you can use "and" to append them. For example:
productproperty = ProductProperty.find_or_create_by_product_id_and_property_id_and_value(:product_id => product.id, :property_id => property.id, :value => d[descname])
There is one minor catch to be aware of. It will always return the object you've specified, even if that object can't be saved due to validation errors. So make sure you check to see if the returned object has an id (or is_valid?). Don't assume its in the database.
Alternatively, you can use the 'bang' version of the method to raise an error if the object cannot be saved:
http://guides.rubyonrails.org/active_record_querying.html#find-or-create-by-bang
This applies to Rails 3.
See http://api.rubyonrails.org/classes/ActiveRecord/Base.html:
With single query parameter:
productproperty = ProductProperty.find_or_create_by_product_id(product.id) { |u| u.property_id => property_id, u.value => d[descname] } )
or extended with multiple parameters:
productproperty = ProductProperty.find_or_create_by_product_id(:product_id => product.id, :property_id => property_id, :value => d[descname]) { |u| u.property_id => property_id, u.value => d[descname] } )
Would work with:
conditions = { :product_id => product.id,
:property_id => property.id,
:value => d[descname] }
pp = ProductProperty.find(:first, :conditions => conditions) || ProductProperty.create(conditions)
In Rails 4, you can use find_or_create_by(attr1: 1, attr2: 2) to find or create by multiple attributes.
You can also do something like:
User.create_with(
password: 'secret',
password_confirmation: 'secret',
confirmation_date: DateTime.now
).find_or_create_by(
email: 'admin#domain.com',
admin: true
)
If you need to create the user with some attributes, but cannot search by those attributes.
You could also use where(...).first_or_create - ActiveRecord::Relation#first_or_create.
product_property_attrs = { product_id: product.id,
property_id: property.id,
value: d[descname] }
product_property = ProductProperty.where(product_property_attrs).first_or_create
I've found in Rails 3.1 you do not need to pass the attributes in as a hash. You just pass the values themselves.
ProductProperty.find_or_create_by_product_id_and_property_id_and_value(
product.id, property.id, d[descname])
I have my json serialization working fine
render :json => "#{current_object.serialize(:json, :attributes => [:id, :name])}
But I also want to add further data to the json before it gets set back to the client. Mainly the auth_token.
Googled around like crazy but I can not find what option serialize will take to allow me to append/merge my other data into the JSON.
Hopting to find something like this...
current_object.serialize(:json, :attriubtes => [:id, name], :magic_option => {:form_authenticity_token => "#{form_authenticity_token}"})
You want the :methods key, which works like :attributes, but will include the results of the methods given. In your case:
current_object.to_json(
:attributes => [:id, :name],
:methods => [:form_authenticity_token]
)
For what it's worth, in a recent Rails I hacked together what you want like this:
sr = ActiveRecord::Serialization::Serializer.new(your_object, some_serialization_options).serializable_record
sr['extra'] = my_extra_calculation(some_parameters)
format.json { render :json => sr }
Where your_object is what you want to serialize, some_serialization_options are your standard :include, :only, etc parameters, and my_extra_calculation is whatever you want to do to set the value.
Jimmy
Hacked it in and moving on...
current_object.serialize(:json, :attributes => [:id, :name]).gsub(/\}$/, ", \"form_authenticity_token\": \"#{form_authenticity_token}\"}")