How can I update serialized data in a Rails/MariaDB backend? - ruby-on-rails

Currently, I have some QueuedImages that become GalleryImages once certain conditions are met.
#image = GalleryImage.new(image_params.except(:tags))
#image.user = current_user
#queued = QueuedImage.new(user: current_user)
#queued.image = #image
Before saving this method, transform the images into JSON:
def image_to_json
self.image_data = #image.to_json(include: :plain_images)
end
I'm trying to update the serialized hash/JSON like this:
def update
#queued = QueuedImage.find(params[:id])
hash_as_string = #queued.image_data
i_data = JSON.parse(hash_as_string.gsub('=>', ':'))
i_data["title"] = params["title"]
i_data["description"] = params["description"]
i_data["folder_id"] = params["folder_id"]
i_data["nsfw"] = params["nsfw"]
i_data["tags"] = params["tags"]
#queued.image_data = i_data
if #queued.save
render json: #queued, scope: current_user
else
render json: #queued.errors.as_json(full_messages: true), scope: current_user, status: :unprocessable_entity
end
end
Which throws me a parse error, what am I doing wrong?
How can I properly update the serialized string?
The thing is that when it transforms from a QueuedImage to a GalleryImage, another method takes that data and evaluates it and creates the new GalleryImage, so it has to be in the exact format, and I believe what I'm doing in the update method is wrong, even though I save it as a string in the DB.

Related

How can I render two objects using "render json:" in a Controller?

I have two objects that I want my index action to return, but I'm struggling to find the syntax to return them both at the same time.
def index
last_day_for_jack = Tacobell.where(owner: "Jack")
last_day_for_pete = Tacobell.where(owner: "Pete")
render json: { last_day_for_jack last_day_for_pete }
end

how to remove duplicacy in database when importing csv file into app that using spree gem

i am using spree gem in my app. I import products from product_controller_decorator.rb using csv file.Three tables like spree_products,spree_variants and
spree_prices are relation. As #prod.save happen then it create one row in spree_products,one in spree_variants and one in spree_prices. then another
spree_variants and spree_prices row form due to #var and #price for corresponding #prod which create duplicacy in both table.This is happens due to
association among three tables.can any one resolve this complicacy.It means it form one row to each table.
def import
require 'csv'
file = params[:file]
CSV.foreach(file.path, headers: true, encoding:'iso-8859-1:utf-8') do |row|
#prod = Spree::Product.new()
#prod.name = row["name"]
#prod.shipping_category_id = row["shipping_category_id"]
#prod.description = row["description"]
#prod.available_on = row["available_on"]
#prod.meta_description = row["meta_description"]
#prod.meta_keywords = row["meta_keywords"]
#prod.tax_category_id = row["tax_category_id"]
#prod.shipping_category_id = row["shipping_category_id"]
#prod.promotionable = row["promotionable"]
#prod.meta_title = row["meta_title"]
#prod.featured = row["featured"]
#prod.supplier_id = row["supplier_id"]
#prod.master.price = row["master_price"]
#prod.save!
#var = Spree::Variant.create(cost_price: row["cost_price"], is_master:1, product_id: #prod.id, sku: row["sku"])
if #var.errors.present?
render json: #var #.errors and return
end
#price = Spree::Price.create(variant_id: #var.id)
if #price.errors.present?
render json: #price #.errors and return
end
end
redirect_to admin_products_path, notice: "products imported."
end
With Spree, the master is created when the product is saved, and the defaults for master is applied to it. Instead of creating a new master variant, #var = Spree::Variant.create, update the master instead. You update the master earlier in the file by assigning #prod.master.price = row["master_price"]. That code isn't failing because master is created with default values before the call to #product.save. The line #price = Spree::Price.create(variant_id: #var.id) Is associating an empty (default) Price with the #prod.master. That is already done, they are supposed to be unique, so there is probably fallout from doing this.
Avoid checking for errors after executing .create. If you want to validate errors, do so before saving. The way to do this is:
#var = Spree::Variant.new(cost_price: row["cost_price"], is_master:1, product_id: #prod.id, sku: row["sku"])
if #var.errors.present?
render json: #var #.errors and return
else #var.save
I would rewrite the block as this:
#prod = Spree::Product.new()
#prod.name = row["name"]
#prod.shipping_category_id = row["shipping_category_id"]
#prod.description = row["description"]
#prod.available_on = row["available_on"]
#prod.meta_description = row["meta_description"]
#prod.meta_keywords = row["meta_keywords"]
#prod.tax_category_id = row["tax_category_id"]
#prod.shipping_category_id = row["shipping_category_id"]
#prod.promotionable = row["promotionable"]
#prod.meta_title = row["meta_title"]
#prod.featured = row["featured"]
#prod.supplier_id = row["supplier_id"]
#prod.master.price = row["master_price"]
#prod.master.sku = row["sku"]
[#prod, #prod.master, #prod.master.price].each do |obj|
render json: obj if obj.errors.present?
end
#prod.save!
Here is the spree-core source: Spree Product Model

Rails how to return single JSON object instead of array of JSON objects?

I am limiting to 1, so I thought it would simple return an object in this case the same as .find_by_email
Code:
# GET /users/:identified/type/:social_type
# Returns a single record - so limit 1
def find
#user = User.where("identified = ? AND social_type = ?", params[:identified], params[:social_type]).limit(1)
if not #user.empty?
render json: #user.as_json, status: :created
else
render json: #user, status: :not_found
end
end
Current Response:
[{"id":7,"voy_num":null,"voy_pin":null}]
How can ensure I return a single JSON object?
To get the single object, use first with where like this:
#user = User.where("identified = ? AND social_type = ?", params[:identified], params[:social_type]).first

Rails Render JSON Object instead of entire array

In my controller I have the present code that results in a JSON array, even though there is only one result:
def getSharedSpecial
#result = Campaign.find_by_sql("SELECT
id
,name
,image
,ad_caption
,ad_details
FROM campaigns
WHERE id = " + params[:shared_campagin_id].to_s + "
LIMIT 1;")
respond_to do |format|
format.html
format.json { render json: { special_shared: #result }}
end
end
returns:
"special_shared":[
{
"id":41,
"name":"tester the way",
"image":{
"url":"/uploads/campaign/image/41/Gilded_pic.jpg"
},
"ad_caption":"yfftitu6",
"ad_details":"jku"
}
]
}
As can be seen given the [], this is a JSON array.
How can I create just an object and not an entire array?
The problem is that find_by_sql always returns an array even though you are only looking for a single record. There is no need to use find_by_sql and you've opened yourself to SQL injection attacks by doing so, so just write the finder the traditional way:
#result = Campaign.select(:id, :name, :image, :ad_caption, :ad_details).find(params[:shared_campagin_id])

rails redirect after create problem

Could anyone help with this problem:
Upon "create", the user is redirected to the url: model/model_id (eg post/1), instead I am redirected to models/url_encoding_object (eg posts/.%23) and there is an "406 Not Acceptable" message in the console.
Typically, upon create, the console's message is "Processing PostsController#create (for 000.0.0.0 at 2009-11-23 12:32:52) [POST]", but with this error, the message is "Processing PostsController#create to # (for 000.0.0.0 at 2009-11-23 12:32:52) [POST]"
I've seen austinfromboston's response and tried his "old fashioned but effective" solution to that similar problem, but it doesn't work for me.
Any help would be greatly appreciated
Controller Code:
# POST /groups
# POST /groups.xml
def create
#group = Group.new(params[:group])
#group.category = params[:category]
#group.user = current_user
#here we add the current user to the membership collection of the group
#membership = #group.memberships.build(params[:membership])
#membership.group = #group
#membership.user = current_user
#membership.initiator = false
#membership.membership_status_id = 2
#and here we set the current_user as the owner of the group
#group_permission = #group.group_permissions.build(params[:group_permission])
#group_permission.membership = #membership
#group_permission.group_role = GroupRole.find_by_name('Owner')
unless params[:metro_area_id].blank?
#group.metro_area = MetroArea.find(params[:metro_area_id])
#group.state = (#group.metro_area && #group.metro_area.state) ?
#group.metro_area.state : nil
#group.country = #group.metro_area.country if (#group.metro_area &&
#group.metro_area.country)
else
#group.metro_area = #group.state = #group.country = nil
end
#group.tag_list = params[:tag_list] || ''
# unless #user.is_in_group?(#group)
# #user.memberships << #group
# end
respond_to do |format|
if #group.save
flash[:notice] = :group_was_successfully_created.l
format.html { redirect_to(group_path(#group.id)) }
else
format.html {
#metro_areas, #states = setup_metro_area_choices_for(#group)
if params[:metro_area_id]
#metro_area_id = params[:metro_area_id].to_i
#state_id = params[:state_id].to_i
#country_id = params[:country_id].to_i
end
render :action => "new"
}
end
end
end
Looks like either your routes are off somewhere or your model_id parameter is not what you are expecting. Might want to check to see what that parameter is being set to.
It's also really hard to give any suggestions without seeing controller code. Can you post the method making this call?
There's a lot of superfluous code, in your controller. It still works, but you're doing a lot of things the hard way.
Your problem is this line:
format.html { redirect_to(groups_path(#group.id)) }
Which redirects to the collective groups url adding the parameter #group.id.
What it should be is
format.html { redirect_to(group_path(#group.id)) }
# POST /groups
# POST /groups.xml
def create
#group = Group.new(params[:group])
#group.category = params[:category]
#group.user = current_user
#here we add the current user to the membership collection of the group
#membership = #group.memberships.build(params[:membership])
#membership.group = #group
#membership.user = current_user
#membership.initiator = false
#membership.membership_status_id = 2
#and here we set the current_user as the owner of the group
#group_permission = #group.group_permissions.build(params[:group_permission])
#group_permission.membership = #membership
#group_permission.group_role = GroupRole.find_by_name('Owner')
unless params[:metro_area_id].blank?
#group.metro_area = MetroArea.find(params[:metro_area_id])
#group.state = (#group.metro_area && #group.metro_area.state) ? #group.metro_area.state : nil
#group.country = #group.metro_area.country if (#group.metro_area && #group.metro_area.country)
else
#group.metro_area = #group.state = #group.country = nil
end
#group.tag_list = params[:tag_list] || ''
unless #user.is_in_group?(#group)
#user.memberships << #group
end
respond_to do |format|
if #group.save
flash[:notice] = :group_was_successfully_created.l
format.html { redirect_to(groups_path(#group.id)) }
else
format.html {
#metro_areas, #states = setup_metro_area_choices_for(#group)
if params[:metro_area_id]
#metro_area_id = params[:metro_area_id].to_i
#state_id = params[:state_id].to_i
#country_id = params[:country_id].to_i
end
render :action => "new"
}
end
end
end
What is this .1 doing at the end of the line??
flash[:notice] = :group_was_successfully_created.l
I tried to run similar code in my environment and it choked on that.
It should also reference:
group_path(id)
not
groups_path(id)

Resources