IMDbPY can't get age restriction - imdb

I can't find how to get the pc rating or age restriction from imbdPy. Can someone assist please. Looking for Age restriction and whether it has one or more of VLSNP. If it's not in this dictionary does it mean it doesn't store it?
{
'tv schedule': 'airing',
'user rating': 'rating',
'plot summary': 'plot',
'plot summaries': 'plot',
'directed by': 'director',
'created by': 'creator',
'writing credits': 'writer',
'produced by': 'producer',
'original music by': 'original music',
'non-original music by': 'non-original music',
'music': 'original music',
'cinematography by': 'cinematographer',
'cinematography': 'cinematographer',
'film editing by': 'editor',
'film editing': 'editor',
'editing': 'editor',
'actors': 'cast',
'actresses': 'cast',
'casting by': 'casting director',
'casting': 'casting director',
'art direction by': 'art direction',
'set decoration by': 'set decoration',
'costume design by': 'costume designer',
'costume design': 'costume designer',
'makeup department': 'make up',
'makeup': 'make up',
'make-up': 'make up',
'production management': 'production manager',
'production company': 'production companies',
'second unit director or assistant director':
'assistant director',
'second unit director': 'assistant director',
'sound department': 'sound crew',
'costume and wardrobe department': 'costume department',
'special effects by': 'special effects',
'visual effects by': 'visual effects',
'special effects company': 'special effects companies',
'stunts': 'stunt performer',
'other crew': 'miscellaneous crew',
'misc crew': 'miscellaneous crew',
'miscellaneouscrew': 'miscellaneous crew',
'crewmembers': 'miscellaneous crew',
'crew members': 'miscellaneous crew',
'other companies': 'miscellaneous companies',
'misc companies': 'miscellaneous companies',
'miscellaneous company': 'miscellaneous companies',
'misc company': 'miscellaneous companies',
'other company': 'miscellaneous companies',
'aka': 'akas',
'also known as': 'akas',
'country': 'countries',
'production country': 'countries',
'production countries': 'countries',
'genre': 'genres',
'runtime': 'runtimes',
'lang': 'languages',
'color': 'color info',
'cover': 'cover url',
'full-size cover': 'full-size cover url',
'seasons': 'number of seasons',
'language': 'languages',
'certificate': 'certificates',
'certifications': 'certificates',
'certification': 'certificates',
'miscellaneous links': 'misc links',
'miscellaneous': 'misc links',
'soundclips': 'sound clips',
'videoclips': 'video clips',
'photographs': 'photo sites',
'distributor': 'distributors',
'distribution': 'distributors',
'distribution companies': 'distributors',
'distribution company': 'distributors',
'guest': 'guests',
'guest appearances': 'guests',
'tv guests': 'guests',
'notable tv guest appearances': 'guests',
'episodes cast': 'guests',
'episodes number': 'number of episodes',
'amazon review': 'amazon reviews',
'merchandising': 'merchandising links',
'merchandise': 'merchandising links',
'sales': 'merchandising links',
'faq': 'faqs',
'parental guide': 'parents guide',
'frequently asked questions': 'faqs'}

No, that's just a list of aliases for some keywords.
The keys you are looking for are:
certificates
mpaa
An example:
>>> import imdb
>>> ia = imdb.IMDb()
>>> he = ia.get_movie('3460252') # The Hateful Eight
>>> print he.get('mpaa')
Rated R for strong bloody violence, a scene of violent sexual content, language and some graphic nudity
>>> print he.get('certificates')
[u'Argentina:16::(with warning)', u'Australia:R18+', u'Austria:16', u'Brazil:18', u'Canada:18A::(Alberta/British Columbia/Manitoba/Ontario)', u'Canada:13+::(Quebec)', u'Chile:14', u'Czech Republic:15', u'Denmark:15', u'Finland:K-16', u'France:12::(with warning)', u'Germany:16', u'Hong Kong:III', u'Hungary:18', u'India:A', u'Ireland:18', u'Italy:T', u'Japan:R18+', u'Japan:R15+::(edited version)', u'Mexico:C', u'Netherlands:16', u'New Zealand:R18', u'Norway:15', u'Portugal:M/16', u'Russia:18+', u'Singapore:R21', u'South Korea:18', u'Spain:18', u'Sweden:15', u'Switzerland:16', u'Taiwan:R-18', u'Thailand:18', u'UK:18', u'USA:R::(certificate #50077)']
))))

Related

ConversationHandler not working when deployed on Heroku but is working good when running on local machine

I am using Python Telegram Bot library to make a bot that has a conversation which let's users name their project, payment plans etc. The conversation consists of MessageHandlers and CallBackQueryHandlers. Thr problem I'm facing is, this conversation was working fine when I was using this bot from my local machine, but when I deployed it to heroku, I can't have the full conversation, it would become unresponsive at some point and I would have to cancel the conversation(which surprisingly, works at lightning bolt speed). All other handlers of my application work as expected and respond quickly.
I am using webhook in this application.
The ConversationHandler:
add_project_handler = ConversationHandler(
entry_points=[CallbackQueryHandler(project_name, pattern="add_project")],
states={
PROJECT_NAME: [MessageHandler(Filters.regex(".*"), store_name_maybe_project_type)],
PROJECT_TYPE: [CallbackQueryHandler(store_type_maybe_admin)],
ADMIN:[CallbackQueryHandler(connect_channel)],
CONNECT:[MessageHandler(Filters.regex(".*"), connect_channel_add_currency)],
CURRENCY:[CallbackQueryHandler(store_currency_maybe_frequency)],
FREQUENCY:[CallbackQueryHandler(store_frequency_maybe_amount)],
MONEY:[MessageHandler(Filters.regex(".*"), store_amount_maybe_bot)],
TOKEN:[MessageHandler(Filters.regex(".*"), store_bot_show_links)],
PAY_SETUP:[CallbackQueryHandler(setup_payment)],
PAYPAL:[MessageHandler(Filters.regex(".*"), handle_client_id)],
CLIENT_ID:[MessageHandler(Filters.regex(".*"), handle_client_secret)],
},
fallbacks=[CommandHandler('cancel', cancel)],
)
handlers.append(add_project_handler)
EDIT:
So I checked out the logs, and I saw some really weird behavior, so it recieves an update, and right now, the state of the conversation should have been 1, but it says 'selecting conversation with state None'. That too it does three times.
2021-10-01T16:55:59.411864+00:00 heroku[router]: at=info method=POST path="/1967487217:AAGDmzoxPPlB386VuEYr4s8dPM50fr49d84" host=invitememberbot.herokuapp.com request_id=6d10ee36-ebe4-40de-91b3-48c5e33d6172 fwd="91.108.6.63" dyno=web.1 connect=0ms service=2ms status=200 bytes=154 protocol=https
2021-10-01T16:55:59.415201+00:00 app[web.1]: 2021-10-01 16:55:59,414 - telegram.ext.dispatcher - DEBUG - Processing Update: {'callback_query': {'chat_instance': '1523769404808794079', 'id': '4756348607585474313', 'data': 'channel', 'message': {'delete_chat_photo': False, 'chat': {'id': 1107423707, 'first_name': 'Palash', 'type': 'private', 'username': 'raghu_palash', 'last_name': 'Raghuwanshi'}, 'channel_chat_created': False, 'date': 1633106830, 'supergroup_chat_created': False, 'reply_markup': {'inline_keyboard': [[{'callback_data': 'channel', 'text': 'Paid Telegram Channel'}]]}, 'group_chat_created': False, 'photo': [], 'caption_entities': [], 'new_chat_members': [], 'message_id': 2657, 'entities': [], 'text': 'What do you want to make?', 'new_chat_photo': [], 'from': {'id': 1967487217, 'first_name': 'InviteMemberBot', 'username': 'InviteMemberFiverrBot', 'is_bot': True}}, 'from': {'language_code': 'en', 'last_name': 'Raghuwanshi', 'id': 1107423707, 'first_name': 'Palash', 'username': 'raghu_palash', 'is_bot': False}}, 'update_id': 334393256}
2021-10-01T16:55:59.415374+00:00 app[web.1]: 2021-10-01 16:55:59,415 - telegram.ext.conversationhandler - DEBUG - selecting conversation (1107423707, 1107423707) with state None
2021-10-01T16:55:59.415584+00:00 app[web.1]: 10.1.90.119 - - [01/Oct/2021:16:55:59 +0000] "POST /1967487217:AAGDmzoxPPlB386VuEYr4s8dPM50fr49d84 HTTP/1.1" 200 2 "-" "-"
2021-10-01T16:55:59.415742+00:00 app[web.1]: 2021-10-01 16:55:59,415 - telegram.ext.conversationhandler - DEBUG - selecting conversation (1107423707, 1107423707) with state None
2021-10-01T16:55:59.415867+00:00 app[web.1]: 2021-10-01 16:55:59,415 - telegram.ext.conversationhandler - DEBUG - selecting conversation (1107423707, 1107423707) with state None
And here's something more weird, when I click the button twice rapidly, it takes me to the next state.
2021-10-01T17:15:24.421256+00:00 heroku[router]: at=info method=POST path="/1967487217:AAGDmzoxPPlB386VuEYr4s8dPM50fr49d84" host=invitememberbot.herokuapp.com request_id=ea099aff-e9dd-46fa-8516-958677290171 fwd="91.108.6.63" dyno=web.1 connect=0ms service=6ms status=200 bytes=154 protocol=https
2021-10-01T17:15:24.420031+00:00 app[web.1]: 2021-10-01 17:15:24,419 - telegram.ext.dispatcher - DEBUG - Processing Update: {'callback_query': {'chat_instance': '1523769404808794079', 'id': '4756348606350994438', 'data': 'channel_done', 'message': {'delete_chat_photo': False, 'chat': {'id': 1107423707, 'first_name': 'Palash', 'type': 'private', 'username': 'raghu_palash', 'last_name': 'Raghuwanshi'}, 'channel_chat_created': False, 'date': 1633107558, 'supergroup_chat_created': False, 'reply_markup': {'inline_keyboard': [[{'callback_data': 'channel_done', 'text': 'Done'}]]}, 'group_chat_created': False, 'photo': [], 'caption_entities': [], 'new_chat_members': [], 'message_id': 2659, 'entities': [], 'text': "Please create a private Telegram channel and click Done when it's ready:", 'new_chat_photo': [], 'from': {'id': 1967487217,
'first_name': 'InviteMemberBot', 'username': 'InviteMemberFiverrBot', 'is_bot': True}}, 'from': {'language_code': 'en',
'last_name': 'Raghuwanshi', 'id': 1107423707, 'first_name': 'Palash', 'username': 'raghu_palash', 'is_bot': False}}, 'update_id': 334393260}
2021-10-01T17:15:24.420209+00:00 app[web.1]: 2021-10-01 17:15:24,420 - telegram.ext.conversationhandler - DEBUG - selecting conversation (1107423707, 1107423707) with state 1
I don't understand why it worked fine when I ran it on my own machine, but does this on heroku.
Additional Information -
These are the functions that are involved in this log:
def store_type_maybe_admin(update, context):
# Open db connection
conn = DB_POOL.getconn()
cur = conn.cursor()
# stores project type and conditonally asks for making admin
query = update.callback_query
query.answer()
keyboard = [[InlineKeyboardButton("Done", callback_data="channel_done")]]
reply_markup = InlineKeyboardMarkup(keyboard)
if query.data != "channel_done":
context.user_data["project_type"] = query.data
q = "UPDATE project SET project_type = %s WHERE id = %s"
cur.execute(q, (query.data, context.user_data["project_id"]))
conn.commit()
message = f"Please create a private Telegram {query.data} and click Done when it's ready:"
video = "BAACAgUAAxkDAAICCGFK8ud7FDZ2qbzOkQfrDId-abgXAAKqAwAC-KBYVquzwMps2x7GIQQ"
return_value = PROJECT_TYPE
else:
message = "Please add this bot (#InviteMemberFiverrBot) to the channel admins. It needs Add Subscribers permission.\n\nPress Done when it's ready:"
video = "BAACAgUAAxkDAAICFmFK9GB185nfUvTeE6P3ZTnEp1YEAAKxAwAC-KBYVtfAgpeMwSB0IQQ"
return_value = ADMIN
# Send a video
context.bot.send_video(chat_id=update.effective_chat.id, video=video)
context.bot.send_message(chat_id=update.effective_chat.id ,text=message, reply_markup=reply_markup, parse_mode="markdown")
DB_POOL.putconn(conn)
return return_value # will be either PROJECT_TYPE = 1 or ADMIN = 2
def connect_channel(update, context):
query = update.callback_query
query.answer()
video = "BAACAgUAAxkDAAICGWFK9ShTxKcIN32o9njkIQMCXcwoAAKyAwAC-KBYVi7hYk0auE7IIQQ"
context.bot.send_video(chat_id=update.effective_chat.id, video=video)
context.bot.send_message(
chat_id=update.effective_chat.id,
text=f"To connect the channel, please forward a message (any) from the channel to this bot."
)
return CONNECT
This is how I have setup my bot:
bot = telegram.Bot(token=TOKEN)
dispatcher = setup(bot, db_pool)
#app.route(f"/{TOKEN}", methods=["POST"])
def respond():
"""Run the bot."""
update = telegram.Update.de_json(request.get_json(force=True), bot)
dispatcher.process_update(update)
return "ok"
the setup function:
def setup(bot, db_pool):
# Create bot, update queue and dispatcher instances
dispatcher = Dispatcher(bot, None, workers=0)
##### Register handlers here #####
initialize_bot_handlers = initialize_bot(db_pool) # initialize_bot returns a list of handlers
for handler in initialize_bot_handlers:
dispatcher.add_handler(handler)
return dispatcher
The conversation handler is inside the initialize_bot function.

How to get corresponding google photo ids and google files?

Users may optionally have their Google Photos show up as a folder in Google Drive. Deleting in Drive deletes in Photos, and vice versa (with exceptions for albums and other gotchas). See https://support.google.com/photos/answer/6156103 for details.
Is it possible to get the correspondence between a Photos mediaItem resource and Drive files resource via the API?
I've already done the naive thing: look for matching and embedded ids in both. No luck. Sample returns from the API are included below. (Ids and URLs were slightly mangled to make them non-functional.)
example mediaItem:
{'id': 'APyCggKCjFW9fw_WJwaa5OUXE4Yp9nO2xk1Srkm9Eb-mA9l2pXRAy4oihnPfcAbez7',
'productUrl': 'https://photos.google.com/lr/album/APyCggJA4K-E0UOQMMAtnShqRVdP057VPEROpkqN2FYZcoVd4v8iz_3bu/photo/APyCggKCjFa8g5W9fw_WJwaaQObO2xk1Srk6Eb-mA9l2pXRAy4oihnPfcAbez7',
'baseUrl': 'https://lh3.googleusercontent.com/lr/AJ-EwvnNBVMKbifgSTnqRPr0qpKpiTE46ONto1IIq3ALLBMQFE14-PEzwTRRwuX0ym35ZIQFavk2HmbyMYtnzElMxoXxQpHOQqot1e-Uh1Y6WzcyPoRnenA1xDwwsnPugsnK0vRdoEPiBMNF25NTnNZ8m7F4Za0Xd-b1FbIYow4BrIFAlKwPfv5g8-tk8CaNoOOTmL5TVoDfJwcOyD7McFdOm4dN-731itNxaYonVF5WVw66-aqQxKRvd-P6HFZ7b_bQQxB9foQLFdOLqVWmF2Jpp5ep801--ekkZF7wSQw-7obcqXLfqi9ieW_OWSjMOh77nkqMwdQ9dhXJ-XgfdDsuzZRrft8338nKsiGyt9EgNT4a26k7A1y9G2phCKFYO7O8Rwhs_uRuX4Lc6c3Tbng_VEt5cTiWO_OiMddGyyWRR4d9gWLTAYeNTDqFHO_0ZhEYjcwbYmBvzgY7Pg1wOxtPj3WtZXXRf5AvpKEOmhHiaIeEh0rwFAbde0E1NBbB7tNm4YOq_YIIxjKnaN4v0OsghB6ah3nVNwVxIszrTCR6DgGCFOCEgJyETLLAmi8aUDDhoyzGqCtpiPZ3FeFozIeimeGbvLTiefjo-39Fiiuc7_vSKFkgOAnDq-gDhRDvwO4SoPm4JrD_4YbTkb_1rmf8Iv26lCplEJJxM4g0_b6MrvE4JEI5uyOf01Rk_Am5v7s7piOdsmAHr7pKVorY3EhU5ezNAgzye9V2Is9cuK2ALQOG17UyH9sxWlHPxtDLKV2Ur8gfem0bqzO2WNjMn_rX_Q27W',
'mimeType': 'image/jpeg',
'mediaMetadata': {'creationTime': '2018-12-25T15:28:26Z',
'width': '2448',
'height': '3264',
'photo': {'cameraMake': 'Apple',
'cameraModel': 'iPhone 6 Plus',
'focalLength': 4.15,
'apertureFNumber': 2.2,
'isoEquivalent': 32}},
'filename': 'IMG_0924.JPG'}
example file:
{'kind': 'drive#file',
'id': '1XXkAo-AL7PXBXNpS27cGBCsHvHOaCtXBgQ',
'name': 'IMG_0924.JPG',
'mimeType': 'image/jpeg',
'description': '',
'starred': False,
'trashed': False,
'explicitlyTrashed': False,
'parents': ['jpWRoFkPQ0mg'],
'spaces': ['photos', 'drive'],
'version': '2',
'webContentLink': 'https://drive.google.com/a/bogus.com/uc?id=1XXkAo-AL77cGBCsHvHOaCtXBgQ&export=download',
'webViewLink': 'https://drive.google.com/a/bogus.com/file/d/1XXkAo-AL77cGBCsHvHOaCtXBgQ/view?usp=drivesdk',
'iconLink': 'https://drive-thirdparty.googleusercontent.com/16/type/image/jpeg',
'hasThumbnail': True,
'thumbnailLink': 'https://lh3.googleusercontent.com/zxSXO-GJkKmVVejNzEYreyx7_wEddrq2VPWsVSCFRdRfiVdI5--oWm00=s220',
'thumbnailVersion': '1',
'viewedByMe': False,
'createdTime': '2018-12-25T15:28:26.000Z',
'modifiedTime': '2019-01-06T16:56:08.000Z',
'modifiedByMeTime': '2019-01-06T16:56:08.000Z',
'modifiedByMe': True,
'owners': [{'kind': 'drive#user',
'displayName': 'Reece Hart',
'photoLink': 'https://lh5.googleusercontent.com/-QYk9j/AAAAAAI/AAAAOFo/PC9sT/s64/photo.jpg',
'me': True,
'permissionId': '03329584261458389005',
'emailAddress': 'reece#bogus.com'}],
'lastModifyingUser': {'kind': 'drive#user',
'displayName': 'Reece Hart',
'photoLink': 'https://lh5.googleusercontent.com/-QYk9i9j/AAAAAAI/AAAAOFo/PC9j/s64/photo.jpg',
'me': True,
'permissionId': '03329584261458389005',
'emailAddress': 'reece#bogus.com'},
'shared': False,
'ownedByMe': True,
'capabilities': {'canAddChildren': False,
'canChangeCopyRequiresWriterPermission': True,
'canChangeViewersCanCopyContent': True,
'canComment': True,
'canCopy': True,
'canDelete': True,
'canDownload': True,
'canEdit': True,
'canListChildren': False,
'canMoveItemIntoTeamDrive': False,
'canReadRevisions': True,
'canRemoveChildren': False,
'canRename': True,
'canShare': True,
'canTrash': True,
'canUntrash': True},
'viewersCanCopyContent': True,
'copyRequiresWriterPermission': False,
'writersCanShare': True,
'permissions': [{'kind': 'drive#permission',
'id': '03329584261458389005',
'type': 'user',
'emailAddress': 'reece#bogus.com',
'role': 'owner',
'displayName': 'Reece Hart',
'photoLink': 'https://lh5.googleusercontent.com/-QYk9i9/AAAAA/AAAA/PC9jsT/s64/photo.jpg',
'deleted': False}],
'permissionIds': ['03329584261'],
'originalFilename': 'IMG_0924.JPG',
'fullFileExtension': 'JPG',
'fileExtension': 'JPG',
'md5Checksum': '7ffdb3f36ba89bcad4b7e3b40a6ef356',
'size': '116216',
'quotaBytesUsed': '0',
'headRevisionId': '1gSdsharFji-NH3dDz9AitkOycA',
'imageMediaMetadata': {'width': 1200,
'height': 1600,
'rotation': 0,
'location': {'latitude': 37.72585277777778,
'longitude': -122.41243611111112,
'altitude': 1075.620606060606},
'colorSpace': 'sRGB'},
'isAppAuthorized': False}
Starting July 10 2019, Google Photos and Google Drive no longer sync, so there no longer is any correspondence between photos in Drive and Photos - they are entirely separate entities.
You can however import photos from Google Drive to Google Photos.

Rails 4.2 : Form with multiple models - param is missing or the value

I'm having trouble with Rails 4.2 to create a form with multiple models.
I'm creating a form to allow a user to order a gift card with a custom stripe payment form all in one.
I tried different ways using form_tag instead of simple_form_for and simple_fields_for and I tried all the solution provided on this website but I can't find a way out of this hell!
My form is the following :
=simple_form_for #giftcard, url: gift_cards_path, html: {"accept-charset" => "UTF-8", :autocomplete => "off", :enctype => "multipart/form-data", :method => "post" } do |f|
(...)
= field_set_tag 'Delivery mode' do
.form-row
= f.label :delivery_mode, 'She receive the mail'
= f.radio_button :delivery_mode, 'email_to_recipient'
= f.label :delivery_mode, 'I receive the mail'
= f.radio_button :delivery_mode, 'email_to_giver'
= f.label :delivery_mode, 'Delivery with in box with a jewel'
= f.radio_button :delivery_mode, 'gift_box', id: 'gift_box'
= field_set_tag 'Who is the gift for ?' do
.form-row
= f.input :recipient_first_name, label: 'First Name'
.form-row
= f.input :recipient_last_name, label: 'Last Name'
.form-row
= f.input :recipient_email, placeholder: 'example#mail.com', label: 'Son adresse email'
.form-row
= f.input :message, placeholder: 'Your message', label: 'Son message'
= f.simple_fields_for :payment do |p|
.form-row
= p.input :card_number, label: 'Numéro de carte'
.form-row
= p.input :card_cvc, input_html: { "size" => 4, "data-stripe" => "cvv" }, label: 'CVV'
.form-row
= p.input :card_expiration_month, input_html: { "placeholder" => "MM", "size" => 2, "data-stripe" => "exp-month" }
= p.input :card_expiration_year, input_html: { "placeholder" => "YYYY", "size" => 4, "data-stripe" => "exp-year" }
.form-row
= f.button :submit, 'Send your gift !'
My controller is the following :
def new
#giftcard = GiftCard.new
#payment = Payment.new
end
def create
#giftcard = GiftCard.new(giftcard_params)
#payment = Payment.new(creditcard_params)
#giftcard.amount += 9.90 if #giftcard.gift_box?
respond_to do |format|
if #giftcard.save && #payment.process_payment
code_coupon = CodeCoupon.create(name: giftcard.coupon, value: 0, category: 'membership', origin: 'gift')
if giftcard.delivery_mode == 'gift_box'
UserMailer.prepare_gift_box(#giftcard)
UserMailer.giftcard_recipe(#giftcard)
elsif #giftcard.delivery_mode == 'email_to_giver'
UserMailer.send_gift_card(#giftcard, #giftcard.giver_email)
UserMailer.giftcard_recipe(#giftcard)
elsif #giftcard.delivery_mode == 'email_to_recipient'
UserMailer.send_gift_card(#giftcard, #giftcard.recipient_email)
UserMailer.giftcard_recipe(#giftcard)
end
format.html { redirect_to #giftcard, notice: 'Votre carte cadeau à bien été créée et vous a été envoyé par email' }
format.json { render :show, status: :created, location: #giftcard }
else
format.html { render :new, locals: { errors: #giftcard.errors.full_messages } }
format.json { render json: #giftcard.errors, status: :unprocessable_entity }
end
end
end
private
def giftcard_params
params.require(:gift_card).permit(:recipient_email, :recipient_first_name, :recipient_last_name, :giver_email, :giver_phone, :giver_first_name, :giver_last_name, :message, :amount, :delivery_mode, :delivery_first_name, :delivery_last_name, :delivery_street, :delivery_city, :delivery_zip)
end
def creditcard_params
params.require(:payment).permit(:card_number, :card_cvc, :card_expiration_month, :card_expiration_year, :card_token )
end
And the troubled model:
class Payment
include ActiveModel::Model
attr_accessor :card_number, :card_cvc, :card_expiration_month, :card_expiration_year, :card_token
validates :card_number, presence: true
validates :card_cvc, presence: true
validates :card_expiration_month, presence: true
validates :card_expiration_year, presence: true
def payment_process
Stripe::Charge.create(
amount: amount * 100,
description: "paiement unique",
source: card_token,
currency: 'eur'
)
end
end
When I try to validate the form, it returns the following error :
ActionController::ParameterMissing - param is missing or the value is empty: payment:
actionpack (4.2.8) lib/action_controller/metal/strong_parameters.rb:251:in require'
app/controllers/gift_cards_controller.rb:56:increditcard_params'
app/controllers/gift_cards_controller.rb:13:in `create'
If I remove the require in the creditcard_params method and I click on submit, I get in the log :
Unpermitted parameter: payment
Unpermitted parameters: utf8, authenticity_token, gift_card, commit
(0.1ms) BEGIN
(0.2ms) ROLLBACK
EDIT
Here the parameters that I receive in the log :
Started POST "/gift_cards" for ::1 at 2017-10-06 10:17:42 +0200
Processing by GiftCardsController#create as HTML
Parameters: {
"utf8"=>"✓",
"authenticity_token"=>"UB1keTN7YNDhaEBdIT6cYf/qrwr/QxCpFEYwvGDBLWmYvZiVjXxFg+bQ9vaPAfQTx32d/D7jHnShsTmsqMwLrA==",
"gift_card"=>{
"recipient_first_name"=>"",
"recipient_last_name"=>"",
"recipient_email"=>"",
"message"=>"",
"giver_first_name"=>"",
"giver_last_name"=>"",
"giver_email"=>"",
"giver_phone"=>"",
"delivery_first_name"=>"",
"delivery_last_name"=>"",
"delivery_street"=>"",
"delivery_city"=>"",
"delivery_zip"=>"",
"payment"=>{
"card_number"=>"",
"card_cvc"=>"",
"card_expiration_month"=>"",
"card_expiration_year"=>""
}
},
"commit"=>"Send your gift !"
}
Thank you in advance for your help,
Regards
In my opinion, one way of achieving this will be, changes in person_params as below
def person_params
params.require(:gift_card).permit(:recipient_email, :recipient_first_name, :recipient_last_name, :giver_email, :giver_phone, :giver_first_name, :giver_last_name, :message, :amount, :delivery_mode, :delivery_first_name, :delivery_last_name, :delivery_street, :delivery_city, :delivery_zip, payment: [:card_number, :card_cvc, :card_expiration_month, :card_expiration_year])
end
This will whitelist all your parameters as you have shown in params,
Once this is done, further you will have to change your create action as
#payment = Payment.new(person_params(params)[:payment])
instead of your code.
Addition to this there is a code change in if condition as per the model you have shown #giftcard.save && #payment.payment_process.
The complete solution will be as below:
def create
#giftcard = GiftCard.new(giftcard_params)
#payment = Payment.new(giftcard_params[:payment])
#giftcard.amount += 9.90 if #giftcard.gift_box?
respond_to do |format|
if #giftcard.save && #payment.payment_process
code_coupon = CodeCoupon.create(name: giftcard.coupon, value: 0, category: 'membership', origin: 'gift')
if giftcard.delivery_mode == 'gift_box'
UserMailer.prepare_gift_box(#giftcard)
UserMailer.giftcard_recipe(#giftcard)
elsif #giftcard.delivery_mode == 'email_to_giver'
UserMailer.send_gift_card(#giftcard, #giftcard.giver_email)
UserMailer.giftcard_recipe(#giftcard)
elsif #giftcard.delivery_mode == 'email_to_recipient'
UserMailer.send_gift_card(#giftcard, #giftcard.recipient_email)
UserMailer.giftcard_recipe(#giftcard)
end
format.html { redirect_to #giftcard, notice: 'Votre carte cadeau à bien été créée et vous a été envoyé par email' }
format.json { render :show, status: :created, location: #giftcard }
else
format.html { render :new, locals: { errors: #giftcard.errors.full_messages } }
format.json { render json: #giftcard.errors, status: :unprocessable_entity }
end
end
end
private
def giftcard_params
params.require(:gift_card).permit(:recipient_email, :recipient_first_name, :recipient_last_name, :giver_email, :giver_phone, :giver_first_name, :giver_last_name, :message, :amount, :delivery_mode, :delivery_first_name, :delivery_last_name, :delivery_street, :delivery_city, :delivery_zip, payment: [:card_number, :card_cvc, :card_expiration_month, :card_expiration_year])
end
end

How to update a polymorphic image in a rake task?

I have a Toilet and Photo model and Photo has a polymorphic association.
I have a rake task that is gathering information from a csv file. I want to update the image but since it's not part of the toilets table I'm having trouble figuring that out. I'm using paperclip to handle my images.
my task looks like this
namespace :import do
desc "Importing toilets from csv"
task toilets: :environment do
filename = File.join Rails.root, "toilets.csv"
counter = 0
CSV.foreach(filename, headers: true) do |row|
toilet = Toilet.create(
name: row['name'],
latitude: row['latitude'],
longitude: row['longitude'],
address: row['address'],
image: row['image']
)
puts "#{toilet} - #{toilet.errors.full_messages.join(",")}" if toilet.errors.any?
counter += 1 if toilet.persisted?
end
puts "Imported #{counter} toilets"
end
end
Toilet Model
has_many :photos, :as => :imageable
accepts_nested_attributes_for :photos
Photo Model
belongs_to :toilet
belongs_to :imageable, :polymorphic => true
has_attached_file :image, styles: { medium: "300x300>", thumb: "100x100>" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/
I figured out how to update the image with the code below. This works but I feel that there might be a cleaner solution.
toilet = Toilet.create(
name: row['name'],
latitude: row['latitude'],
longitude: row['longitude'],
address: row['address']
)
photo = Photo.create(
image: row["image"],
imageable_type: "Toilet",
imageable_id: toilet.id
)

How to attach SKU to Product via BigCommerce API; The field 'product_option_id' is invalid

I've been banging my head against this for a while so am hoping someone can help. Ruby/HTTParty/BigCommerce Gem (where it works).
Error is: The field 'product_option_id' is invalid ; when trying to add an SKU via
myresponse = HTTParty.post("#{#store_url}products/800/skus",
:body=>{
:sku => "111204",
:options => [
{
:product_option_id => 16,
:option_value_id => 46
}
]
}.to_json,
:headers => {'Content-Type' => 'application/json' },
:basic_auth => #auth)
Basically I can't see/figure out where 'product_option_id' is referring to; you can't directly link options to products via the API that I can see.
There are two other questions on SO re this issue but neither had useful answers for me.
Prior to this, I've;
Created a product; id is 800, sku is 111240P. Response to \products?sku=111240P is
{"id"=>"800", "keyword_filter"=>"NULL", "name"=>"Opaque Thigh High", "type"=>"physical", "sku"=>"111204P", "description"=>"Opaque nylon thigh high.", "search_keywords"=>nil, "availability_description"=>nil, "price"=>"3.8200", "cost_price"=>"2.1800", "retail_price"=>"0.0000", "sale_price"=>"0.0000", "calculated_price"=>"3.8200", "sort_order"=>"0", "is_visible"=>"true", "is_featured"=>"false", "related_products"=>"NULL", "inventory_level"=>"0", "inventory_warning_level"=>"0", "warranty"=>"NULL", "weight"=>"0.1000", "width"=>"4.0000", "height"=>"0.2500", "depth"=>"8.0000", "fixed_cost_shipping_price"=>"0.0000", "is_free_shipping"=>"false", "inventory_tracking"=>"simple", "rating_total"=>"0", "rating_count"=>"0", "total_sold"=>"0", "date_created"=>"Sat, 27 Sep 2014 11:45:14 +0000", "brand_id"=>"135", "view_count"=>"0", "page_title"=>nil, "meta_keywords"=>"NULL", "meta_description"=>"NULL", "layout_file"=>"product.html", "is_price_hidden"=>"false", "price_hidden_label"=>nil, "categories"=>{"value"=>"2"}, "date_modified"=>"Sat, 27 Sep 2014 11:45:14 +0000", "event_date_field_name"=>nil, "event_date_type"=>"none", "event_date_start"=>nil, "event_date_end"=>nil, "myob_asset_account"=>nil, "myob_income_account"=>nil, "myob_expense_account"=>nil, "peachtree_gl_account"=>nil, "condition"=>"New", "is_condition_shown"=>"true", "preorder_release_date"=>nil, "is_preorder_only"=>"false", "preorder_message"=>nil, "order_quantity_minimum"=>"0", "order_quantity_maximum"=>"0", "open_graph_type"=>"product", "open_graph_title"=>nil, "open_graph_description"=>nil, "is_open_graph_thumbnail"=>"true", "upc"=>"714718006338", "date_last_imported"=>nil, "option_set_id"=>"NULL", "tax_class_id"=>"0", "option_set_display"=>"right", "bin_picking_number"=>nil, "custom_url"=>"/Opaque-Thigh-High/", "primary_image"=>{"id"=>"0", "zoom_url"=>"NULL", "thumbnail_url"=>"NULL", "standard_url"=>"NULL", "tiny_url"=>"NULL"}, "availability"=>"available", "brand"=>{"link"=>{"content"=>"/brands/135", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/brands/135.xml"}}, "downloads"=>{"link"=>{"content"=>"/products/800/downloads", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/downloads.xml"}}, "images"=>{"link"=>{"content"=>"/products/800/images", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/images.xml"}}, "discount_rules"=>{"link"=>{"content"=>"/products/800/discountrules", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/discountrules.xml"}}, "configurable_fields"=>{"link"=>{"content"=>"/products/800/configurablefields", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/configurablefields.xml"}}, "custom_fields"=>{"link"=>{"content"=>"/products/800/customfields", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/customfields.xml"}}, "videos"=>{"link"=>{"content"=>"/products/800/videos", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/videos.xml"}}, "skus"=>{"link"=>{"content"=>"/products/800/skus", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/skus.xml"}}, "rules"=>{"link"=>{"content"=>"/products/800/rules", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/rules.xml"}}, "option_set"=>"NULL", "options"=>{"link"=>{"content"=>"/products/800/options", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/products/800/options.xml"}}, "tax_class"=>{"link"=>{"content"=>"/taxclasses/0", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/taxclasses/0.xml"}}}},
Created Options and Option Values; The option is called 'Color', id of 25, and the values I want to add to the Option set are; Green (id 46), Black (id 45) and Red (id 44)
HTTParty.get("#{#store_url}options/25", :basic_auth => #auth)
=> #{"id"=>"25", "name"=>"Color", "display_name"=>"Color", "type"=>"RT", "values"=>{"link"=>{"content"=>"/options/25/values", "rel"=>"resource", "href"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/options/25/values.xml"}}}},
Option values:
HTTParty.get("#{#store_url}options/25/values", :basic_auth => #auth)
=> #{"value"=>[{"id"=>"42", "option_id"=>"25", "label"=>"Gold", "sort_order"=>"0", "value"=>"Gold"}, {"id"=>"43", "option_id"=>"25", "label"=>"Silver", "sort_order"=>"0", "value"=>"Silver"}, {"id"=>"44", "option_id"=>"25", "label"=>"Red", "sort_order"=>"0", "value"=>"Red"}, {"id"=>"45", "option_id"=>"25", "label"=>"Black", "sort_order"=>"0", "value"=>"Black"}, {"id"=>"46", "option_id"=>"25", "label"=>"Green", "sort_order"=>"0", "value"=>"Green"}, {"id"=>"47", "option_id"=>"25", "label"=>"White", "sort_order"=>"0", "value"=>"White"}]}}
Created an option set called '111240P'; its id is 26
api.create_optionset(:name=>"111204P")
{"id"=>26, "name"=>"111204P", "options"=>{"url"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/optionsets/26/options.json", "resource"=>"/optionsets/26/options"}}
Linked the Options to the Option Set via;
new_option_set_value = api.create_optionset_option(26, options={
:option_id => 25,
:display_name => "Colors",
:sort_order => 1,
:is_required => true
})
which returns
{"id"=>16, "option_id"=>25, "option_set_id"=>26, "display_name"=>"Colors", "sort_order"=>1, "is_required"=>true, "option"=>{"url"=>"https://store-w1w68tq.mybigcommerce.com/api/v2/options/25.json", "resource"=>"/options/25"}, "values"=>[{"label"=>"Gold", "sort_order"=>0, "value"=>"Gold", "option_value_id"=>42}, {"label"=>"Silver", "sort_order"=>0, "value"=>"Silver", "option_value_id"=>43}, {"label"=>"Red", "sort_order"=>0, "value"=>"Red", "option_value_id"=>44}, {"label"=>"Black", "sort_order"=>0, "value"=>"Black", "option_value_id"=>45}, {"label"=>"Green", "sort_order"=>0, "value"=>"Green", "option_value_id"=>46}, {"label"=>"White", "sort_order"=>0, "value"=>"White", "option_value_id"=>47}]}
So then I go to do the SKU code at the beginning of the question and I get the error mentioned.
I've tried 16, 26, and 25 as the product option ID's without any luck.
The SKU resource is the only one I can see that allows you to tie all this back to a product.
Any help greatly appreciated.
MORE INFO
HTTParty.get("#{#store_url}products/800/options", :basic_auth => #auth)
=> #<HTTParty::Response:0x10 parsed_response=nil, #response=#<Net::HTTPNoContent 204 No Content readbody=true>
CLOSING OUT THE QUESTION
After beret's advice it all works properly. Note that based on my understanding, the below is contrary to the docs.
Put call; 26 being my option_set I'm attaching to the product
myresponse = HTTParty.put("#{#store_url}products/800",
:body=>{
:option_set_id => 26
}.to_json,
:headers => {'Content-Type' => 'application/json' },
:basic_auth => #auth)
Check the options on the product:
HTTParty.get("#{#store_url}products/800/options", :basic_auth => #auth)
Response:
{"options"=>{"option"=>{"id"=>"7", "option_id"=>"25", "display_name"=>"Colors", "sort_order"=>"1", "is_required"=>"true"}}}
Go back to SKU and add it, note the 7 from the product/option;
myresponse = HTTParty.post("#{#store_url}products/800/skus",
:body=>{
:sku => "111204",
:options => [
{
:product_option_id => 7,
:option_value_id => 46
}
]
}.to_json,
:headers => {'Content-Type' => 'application/json' },
:basic_auth => #auth)
Response:
{"sku"=>{"id"=>"7", "product_id"=>"800", "sku"=>"111204", "cost_price"=>"0.0000", "upc"=>nil, "inventory_level"=>"0", "inventory_warning_level"=>"0", "bin_picking_number"=>nil, "options"=>{"option"=>{"product_option_id"=>"7", "option_value_id"=>"46"}}}}
product_option_id is referring to Product Option ID, see Product Option Resource (API Reference).
You should be able to get it by requesting /api/v2/products/800/options.xml
If the endpoint above returns empty content, it means, that the product has not been linked with any Option Set. You can do so, by updating the product via PUT request to /api/v2/products/800 with payload like this:
{ "option_set_id": 14 }
If you are not sure what's the option_set_id, checkout: /api/v2/options
All these features around Options/Option Sets are very generic, which may be confusing at first, but on the other hand handy in some advanced scenarios.

Resources