Giter Site home page Giter Site logo

shopify-api-ruby's Introduction

Shopify API Library for Ruby

License: MIT Build Status

This library provides support for Ruby Shopify apps to access the Shopify Admin API, by making it easier to perform the following actions:

  • Creating online or offline access tokens for the Admin API via OAuth
  • Making requests to the REST API
  • Making requests to the GraphQL API
  • Registering/processing webhooks

In addition to the Admin API, this library also allows querying the Storefront API.

You can use this library in any application that has a Ruby backend, since it doesn't rely on any specific framework — you can include it alongside your preferred stack and use the features that you need to build your app.

Note: These instructions apply to v10 or later of this package. If you're running v9 in your app, you can find the documentation in this branch.

Use with Rails

If using in the Rails framework, we highly recommend you use the shopify_app gem to interact with this gem. Authentication, session storage, webhook registration, and other frequently implemented paths are managed in that gem with easy to use configurations.

Requirements

To follow these usage guides, you will need to:

  • have a working knowledge of ruby and a web framework such as Rails or Sinatra
  • have a Shopify Partner account and development store
  • have an app already set up in your test store or partner account
  • add the URL and the appropriate redirect for your OAuth callback route to your app settings

Installation

Add the following to your Gemfile:

gem "shopify_api"

or use bundler:

bundle add shopify_api

Steps to use the Gem

Setup Shopify Context

Start by initializing the ShopifyAPI::Context with the parameters of your app by calling ShopifyAPI::Context.setup (example below) when your app starts (e.g application.rb in a Rails app).

ShopifyAPI::Context.setup(
  api_key: "<api-key>",
  api_secret_key: "<api-secret-key>",
  host: "<https://application-host-name.com>",
  scope: "read_orders,read_products,etc",
  is_embedded: true, # Set to true if you are building an embedded app
  api_version: "2022-01", # The version of the API you would like to use
  is_private: false, # Set to true if you have an existing private app
)

Performing OAuth

You need to go through OAuth as described here to create sessions for shops using your app. The Shopify API gem tries to make this easy by providing functions to begin and complete the OAuth process. See the Oauth doc for instructions on how to use these.

Register Webhooks and a Webhook Handler

If you intend to use webhooks in your application follow the steps in the Webhooks doc for instructions on registering and handling webhooks.

Start Making Authenticated Shopify API Requests

Once your app can perform OAuth, it can now make authenticated Shopify API calls, see docs for:

Breaking Change Notices

Breaking change notice for version 15.0.0

See BREAKING_CHANGES_FOR_V15

Breaking change notice for version 10.0.0

See BREAKING_CHANGES_FOR_V10

Breaking changes for older versions

See BREAKING_CHANGES_FOR_OLDER_VERSIONS

Developing this gem

After cloning the repository, you can install the dependencies with bundler:

bundle install

To run the automated tests:

bundle exec rake test

We use rubocop to lint/format the code. You can run it with the following command:

bundle exec rubocop

shopify-api-ruby's People

Contributors

alexaitken avatar andyw8 avatar costford avatar dependabot[bot] avatar dylanahsmith avatar flavorjones avatar garethson avatar ignacio-chiazzo avatar jamiemtdwyer avatar jstorimer avatar jtgrenz avatar kevinhughes27 avatar klenotiw avatar lizkenyon avatar maartenvg avatar manumilou avatar mikee649 avatar mkevinosullivan avatar mllemango avatar mohs avatar nelsonwittwer avatar nwtn avatar paulomarg avatar peterjm avatar phoet avatar shaynep avatar soleone avatar swalkinshaw avatar tatsuya avatar zzooeeyy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

shopify-api-ruby's Issues

Calling Theme returns 'ForbiddenAccess'

I'm trying to get a list of themes for my store using this: ShopifyAPI::Theme.find(:all)

But that returns this error:

ActiveResource::ForbiddenAccess
Failed.  Response code = 403.  Response message = Forbidden.

I'm able to access all other resources that I've tried. (Orders, Pages, Products, Blogs, etc).

Missing site URI

I'm trying to access the current ShopifyAPI::Shop directly after a user has logged in:

class SessionsController < ApplicationController
  def show
    response = request.env['omniauth.auth']
    if response.present?
      auth_token = response['credentials']['token']
      session[:shopify] = ShopifyAPI::Session.new(params[:shop], auth_token)

      # This is where the error happens:
      Rails.logger.debug ShopifyAPI::Shop.current

      redirect_to root_path, notice: 'Successfully logged in.'
    else
      flash[:error] = 'Could not log in to Shopify shop.'
      redirect_to action: 'new'
    end
  end
end

Which raises the following error:

ArgumentError - Missing site URI:
  activeresource (4.0.0) lib/active_resource/connection.rb:35:in `initialize'
  activeresource (4.0.0) lib/active_resource/base.rb:590:in `connection'
  activeresource (4.0.0) lib/active_resource/base.rb:599:in `connection'
  activeresource (4.0.0) lib/active_resource/base.rb:982:in `find_one'
  activeresource (4.0.0) lib/active_resource/base.rb:876:in `find'
  shopify_api (3.1.8) lib/shopify_api/resources/shop.rb:6:in `current'
  app/controllers/sessions_controller.rb:9:in `show'

theme_id not stored in prefix options from Asset.find

When Asset.find is called with theme_id in the params, then the theme_id is used for the path_prefix, but not stored in the resulting objects prefix_options. As a result, saves will occur on the published rather than unpublished theme returned by the find method.

asset = ShopifyAPI::Asset.find 'templates/index.liquid', params => { :theme_id => unpublished_theme.id }
asset.prefix_options # => {}
asset.value # => "old value"
asset.value = "new value"
asset.save # => true
asset = ShopifyAPI::Asset.find 'templates/index.liquid', params => { :theme_id => unpublished_theme.id }
asset.value # => "old value"

The reason this is happening, is that ActiveResource::Base doesn't use split_options(options[:params]) to instantiate_record with the prefix options in find_one, even though it does this for find_single:

        # Find a single resource from a one-off URL
        def find_one(options)
          case from = options[:from]
          when Symbol
            instantiate_record(get(from, options[:params]))
          when String
            path = "#{from}#{query_string(options[:params])}"
            instantiate_record(connection.get(path, headers))
          end
        end

        # Find a single resource from the default URL
        def find_single(scope, options)
          prefix_options, query_options = split_options(options[:params])
          path = element_path(scope, prefix_options, query_options)
          instantiate_record(connection.get(path, headers), prefix_options)
        end

So the find request will look like this:
GET "/admin/themes/4/assets.json?asset%5Bkey%5D=templates%2Findex.liquid&theme_id=4"
where theme_id became a query parameter, rather then being stored in the returned object.

ActiveModel::Serializer Monkey patch causing issues with existing app api functionality

Hi guys, I work over at Code School. Recently I've been building some functionality that allows us to send digital gift cards to users after purchasing the item from our shopify store, we do this so people can also purchase swag at the same time. Using the gem, this chunk of code breaks all of our current api settings within code school:

module ActiveModel
  module Serializers
    module JSON
      def as_json(options = nil)
        root = options[:root] if options.try(:key?, :root)
        if include_root_in_json
          root = self.class.model_name.element if root == true
          { root => serializable_hash(options) }
        else
          serializable_hash(options)
        end
      end
    end
  end

This looks like a round about way to always require a :root option to be passed to as_json, so even if we have include_root_in_json set to true, we get nil in the top level of the json response unless we send in the root param to render in the controller.

It's not realistic to have to do this. I've since done some hacky stuff to only load the gem while the background job is running to fulfill orders and am currently rolling a custom api wrapper to replace this gem. The easiest solution to this is to just remove this patch altogether, the gem appears at first glance to work fine without it, but I'm not sure what that does to your shopify api tests on your end.

There are a few other monkey patches in ActiveResource::Connection which I didn't have time to look into in any detail that were causing odd problems in other parts of the site, if I happen to stumble on them in the next few days I'll open another issue. Thanks guys.

response body is nil

Hi,

Another fun one for the Net::HTTP crowd. Been seeing sporadic issues from this code in session.rb:

response = access_token_request(code)
if response.code == "200"
  token = JSON.parse(response.body)['access_token']
else
  raise RuntimeError, response.msg
end

The response.code method exists and is 200, but the response body is nil. Is there a better way to handle the underlying reason no body would be returned? It is likely the token at fault but it seems handling this is awkward as there is no mention of the source of the troubles.

Intermittent test failures on test:logging

Where intermittent is over 50% of the time, but not 100%.

  1) Failure:
test:logging on #find(LogSubscriberTest)
    [/Users/lydiakrupp-hunter/shopify_api/test/detailed_log_subscriber_test.rb:31:in `test:logging on #find'
     /Library/Ruby/Gems/1.8/gems/mocha-0.13.3/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:29:in `__send__'
     /Library/Ruby/Gems/1.8/gems/mocha-0.13.3/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:29:in `run']:
<"Headers: {\"Accept\"=>\"application/json\", \"User-Agent\"=>\"ShopifyAPI/3.0.3 ActiveResource/3.2.13 Ruby/1.8.7\"}"> expected but was
<"Headers: {\"User-Agent\"=>\"ShopifyAPI/3.0.3 ActiveResource/3.2.13 Ruby/1.8.7\", \"Accept\"=>\"application/json\"}">.

  2) Failure:
test:logging on #find with an error(LogSubscriberTest)
    [/Users/lydiakrupp-hunter/shopify_api/test/detailed_log_subscriber_test.rb:46:in `test:logging on #find with an error'
     /Library/Ruby/Gems/1.8/gems/mocha-0.13.3/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:29:in `__send__'
     /Library/Ruby/Gems/1.8/gems/mocha-0.13.3/lib/mocha/integration/test_unit/ruby_version_186_and_above.rb:29:in `run']:
<"Headers: {\"Accept\"=>\"application/json\", \"User-Agent\"=>\"ShopifyAPI/3.0.3 ActiveResource/3.2.13 Ruby/1.8.7\"}"> expected but was
<"Headers: {\"User-Agent\"=>\"ShopifyAPI/3.0.3 ActiveResource/3.2.13 Ruby/1.8.7\", \"Accept\"=>\"application/json\"}">.

A few examples in REAME.md

A couple examples in the README.md would have saved me about two hours of time this evening. The syntax is pretty non-intuitive

ShopifyAPI::Product.find(:all, :params => {:limit => 10})

Wouldn't this be more natural?

ShopifyAPI::Product.find(:limit => 10)

undefined method `strip' for nil:NilClass

Hi guys. I am trying to get customer.id from my shopify shop to another app, to be able to autocomplete fields with this shopify customer's name and email.

I made a link from shopify to external app as follows:
a href="myapp/controller/{{customer.id}}">Click here

and in my app controller I have a show action where I want to obtain those attributes (name, email):
@shopify_user_id = params[:id]

if @shopify_user_id.present?
  session[:name] = ShopifyAPI::Customer.find(@shopify_user_id).first_name
  session[:email] = ShopifyAPI::Customer.find(@shopify_user_id).email
end

but I am running a "undefined method `strip' for nil:NilClass" error.

Could you please guide me through this?

Thank you in advance!
UPD:

When I try:
session[:name] ||= ShopifyAPI::Customer.find(@shopify_user_id).first_name
session[:email] ||= ShopifyAPI::Customer.find(@shopify_user_id).email

I'm getting "undefined method `[]' for #ShopifyAPI::Session:0x007fdda1b29f18" ..

Undefined Method Exception for RecurringApplicationCharge.current 404 Error

For shops that return a 404 Not Found, invoking ShopifyAPI::RecurringApplicationCharge.current results in a NoMethodError:

INFO -- : GET https://foo.myshopify.com:443/admin/shop.json
INFO -- : --> 404 Not Found 22 (705.7ms)
INFO -- : Headers: {"Accept"=>"application/json", "User-Agent"=>"ShopifyAPI/3.2.4 ActiveResource/4.0.0.threadsafe Ruby/2.1.2", "X-Shopify-Access-Token"=>"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
INFO -- : Response:
{"errors":"Not Found"}
NoMethodError: undefined method `find' for nil:NilClass
    from lib/ruby/gems/2.1.0/gems/shopify_api-3.2.4/lib/shopify_api/resources/recurring_application_charge.rb:7:in `current'

Rather than a ActiveResource::ResourceNotFound which would seem more expected.

API calls need to return the time that the api limit will reset

TLDR

I want to be a good citizen with respect to API limit. Because my app has both internal and external concurrency, I can't unless I know when the api limit will reset.

Detailed description

Without knowing when the api limit will reset I can't avoid spamming you, in any customer-facing app functionality (example: shipping calculation)

If I'm making requests in a single threaded single user tool, I can keep track of API usage & timing and it will more or less work (although I'll still occasionally spam you when another app is using up calls)

But for the things like shipping rate calculation, I can't get away with sequential calls to the api, it adds too much latency to a process that already typically has 3-7 seconds latency. To be a good citizen I want to fire 1 api request, check the limit, then fire the rest in parallel. Thus my app has internal concurrency

I used typhoeus/hydra to do this, setting the concurrency to 20 instead of the default 200 and adding an on-complete to each request to pause/cancel the hydra if any request hits the api limit.

However, if there is not enough requests left, I have no idea how long to sleep. Even if I always bail on requests instead of sleeping and retrying, the web app itself still has however much external concurrency we buy on heroku -- the minimum is 3-4 for a free app, using unicorn. So if 2 or 3 requests overlap, some of them will end up spamming you (unless I wanted to make it so my whole web app stalls for 5 minutes whenever I bump against the api limit, which my clients would not be very happy with)

If you were to tell me in a header in each api response the time the api limit is going to reset, I could track that globally using memcached, and be a good citizen. All incoming requests to my app could check the api call headroom & the time when it will reset and decide whether to wait for the reset or bail. I would occasionally spam you when some other app bumped against the api limit, but usually with only 1 request in a 5 minute block (occasionally with a parallel block of requests when the other app used up the limit in between my checking and firing my parallel block of requests)

My clients (who are also your clients) would benefit, because the app will seem faster under load (requests only bail when they have to, and only stall as long as they need to)

If you add this header, I promise to package & publish on github my typhoeus-based client that uses it to be a good, mostly non-spamming fast api consumer.

source_name: "web" causes receipt to be sent.

Took me a few hours, but I finally managed to track down this "undocumented feature".

In my app, I was unable to turn off send_receipt and send_fulfillment_receipt behaviours for order creation. I could create orders in the console just fine, no receipt would be sent, but in my sweet app any order creation for a real order would result in emails being sent.

Here is a simple example, in which I create an order twice. Once with the params from the API docs for order creation, and once with the additional field source_name: "web".

# these are the params from the API docs
ShopifyAPI::Order.create({ 
    order: { 
        email: "[email protected]", 
        fulfillment_status: "fulfilled", 
        line_items: [ { 
            variant_id: 396134081, 
            quantity: 1 
        }]
    }
})
# same params, but with source_name: "web"
ShopifyAPI::Order.create({ 
    order: { 
        email: "[email protected]", 
        fulfillment_status: "fulfilled",
        source_name: "web", 
        line_items: [ { 
            variant_id: 396134081, 
            quantity: 1 
        }]
    }
})

The first one fires just fine, creating a resource and not sending email to razmantle. The second sends an order confirmation message to our honoured friend. I've also tried the same experiment with send_receipt explicitly set to false, which is ignored.

I've included a screenshot of razmantle's mailbox...
razmantle's inbox

After running the following commands in the console...
console talk

No hard feelings, folks: I'm just glad to be able to move on with my life ^o^//

Variant product_id

When grabbing a variant, I can't seem to get the product_id, even though the API Doc says it should be available. Is there a way to get the product id from the variant? Am I missing something?

Here are the attribute keys I get from a variant:

["price", "position", "created_at", "requires_shipping", "title", "inventory_quantity", "compare_at_price", "inventory_policy", "updated_at", "inventory_management", "id", "taxable", "grams", "sku", "option1", "fulfillment_service", "option2", "option3"]

I'm using the API Gem v 3.0.0.

Thanks!

Updating product when option already exists gives "Options are not unique"

Details in this discussion that was last updated December 2012:
http://stackoverflow.com/questions/12658002/what-is-the-best-way-to-prevent-to-see-options-are-not-unique-error

Chris Saunders says:

there is a bug in the API when updating products and you are passing in an option that already exists. The error message is actually quite misleading and is being worked on at the moment.

I'm running into this in v3.0.3. Any progress on this or workaround?

Last update by Chris was:

The issue seemed trivial on the surface but there's a bit of work that needs to be done so we haven't had the chance to properly fix it yet.

Fulfillment finder problems

Given a valid Order received with the orders/paid webhook, I have intermittent errors with v3.0.1.

A call ShopifyAPI::Fulfillment.first(:params => {:order_id => 12345689}) will not return nil or a Fulfillment object, but instead errors out on not having a first method on nil Object.

400 error when creating a page

When I create a page from command line using the shopify_api gem (3.1.0), I get this message:

ActiveResource::BadRequest: Failed.  Response code = 400.  Response message = Bad Request.
irb(main):001:0> require 'rubygems'
=> false
irb(main):002:0> require 'shopify_api'
=> false
irb(main):002:0> ShopifyAPI::Base.site = "https://apikey:[email protected]/admin";
irb(main):002:0> ShopifyAPI::Page.create(:body_html => "text", :title => "text")
ActiveResource::BadRequest: Failed.  Response code = 400.  Response message = Bad Request.

I feel like I'm missing something but can't find anything relevant in the docs.

LoginController#authenticate - undefined method 'create_permission_url'

Hi Everyone,

Everytime I want to login with one of my Test Shops I get this error:

error

The only thing I have in that line is

code

Sometimes I get this error in my application, and normally it works after a couple of tries, but this time I can't get my application to work. This is just after I insert the shop url.

I never knew why this is happening, and now I don't know how to fix this, because it always worked, and this seems to be the same code has this one in here:

http://rdoc.info:8080/github/Shopify/shopify_api/master/ShopifyAPI/Session#create_permission_url-instance_method

I also tried to do

s = ShopifyAPI::Session.new(params[:shop])
s..valid? # return was false

Thank you for your time

Add Metafield resource to Article resource

Hi,

Could you kindly add the ability to add a Metafield resource to an Article resource and correspondingly the ability to add a link to a shop where the merchant is editing an Article resource, so that the link can activate an App with the Article resource ID and thereby allow CRUD for Metafield resources attached to an Article resource.

Thanks

Problem with the gemspec file with ruby 1.9.2

I'm getting this error message, it does not like the ’ character... I replaced it by ' and that works.

/Users/patrick/.rvm/gems/ruby-1.9.2-p0/gems/bundler-1.0.0/lib/bundler.rb:227:in `eval': /Users/patrick/Projects/shop_dilara_admin/vendor/gems/shopify_api/shopify_api.gemspec:17: invalid multibyte char (US-ASCII) (SyntaxError)
/Users/patrick/Projects/shop_dilara_admin/vendor/gems/shopify_api/shopify_api.gemspec:13: invalid multibyte char (US-ASCII)
/Users/patrick/Projects/shop_dilara_admin/vendor/gems/shopify_api/shopify_api.gemspec:13: syntax error, unexpected $end, expecting keyword_end
...isolation. In other words, we’ve tried to make the API fol...
... ^

Delete all metafields for a product

There is an very easy way to delete all images of an product:

product = ShopifyAPI::Product.find("...")
product.images = []
product.save

But because the metafield object doesn't seam to be a real child object of product, I can't clear the metafields in the same way.
Is there an easy way to clear all metafields of my product?

API Calls without logging in / setting session from database Fails

I am attempting to set the session and credentials directly so I can do some API Calls via a Proxy App.

I have tried several different ways and each one fails. The most progress I have is getting to the point where it just redirects my requests to the login page.

Each method I tried I have tried it using the core myshopify url and the long ssl url with key:token and /admin

I tried base site, active resource site, create new session, set temp session etc.

I have tried clearing the session before setting the new one as well

Everything I try I simply call the proxy page and it forwards my url to /login which on the actual app page would be where I enter a store url and login etc...

I verify all incoming requests are from the proxied shop itself using Shopify's security methods and comparing signatures etc.

I just want it so a user can go to the proxy app url on their storefront and have it issue a shopifyAPI call. In this example I was simply trying to pull a list of all orders.

using the stored data (url and token in the apps database)

I simply cannot figure this out.

Any help would be appreciated.

@orders = ShopifyAPI::Session.temp("https://#{myapp::Application.config.shopify.api_key}:#{@shop.shopToken}@#{@shop.shopUrl}/admin", @shop.shopToken) { ShopifyAPI::Order.find(:all) }
@orders = ShopifyAPI::Session.temp(@shop.shopUrl, @shop.shopToken) { ShopifyAPI::Order.find(:all) }

Updating Fulfillments

Hi,

I have a cycle to complete. Merchant is fulfilling orders using a custom fulfillment service. The act of fulfilling triggers a webhook to the fulfillment centre where they take some time to fulfill and generate a tracking number.

I need to update the existing fulfillment to reflect the tracking number and quantities actually fulfilled.

There is no way to do this with the API gem code? How does one update existing fulfillments?

Update gem please

Hi,

Lydia, you made a patch to fix a bug with article details, but never pushed a new gem out with that patch. I would prefer to not Monkey Patch... could you kindly push a version of this gem with that patch please!

Thanks

Deleting a Product Image resource fails API v 3.4.2

Given a Product with Images we can iterate product.images

Given an instance of an image eg:

img = ShopifyAPI::Product.find(260391085).images.first
=> #<ShopifyAPI::Image:0x007fb4b9375bc0 @attributes={"created_at"=>"2014-03-08T20:37:26-05:00", "id"=>570863025, "position"=>1, "updated_at"=>"2014-03-08T20:37:26-05:00", "src"=>"https://cdn.shopify.com/s/files/1/0084/3892/products/calice1_2013.jpg?v=1394329046"}, @prefix_options={:product_id=>260391085}, @persisted=true>

We can see we get the parent product ID in the product_options attribute:

@prefix_options={:product_id=>260391085}

Trying to delete this image resource fails however.

ShopifyAPI::Image.delete(img.id)
ActiveResource::MissingPrefixParam: product_id prefix_option is missing

It would be nice to factor image resource deletes into the API.

Return customer objects when searching for customers

If I do the following:

customers = ShopifyAPI::Customer.get(:search, :q => some_search_query)

it returns an array of hashes representing each customer. Is there any way that this could return an array of ShopifyAPI::Customer objects instead?

Currently we have to make another API call to get the customer object in order to update it, which seems a bit redundant.

Thanks.

Finding a product and saving variants results in POST requests

product = ShopifyAPI::Product.find(:first)
variant = product.variants.first
puts variant.new_record? # => true
variant.price = variant.price + 1
variant.save # => false
puts variant.errors.full_messages # => Options are not unique

Tested using activeresource gem version 3.2.2, and haven't checked how many versions this affects.

That save actually ends up doing a POST request because new_record? is true for the variant. The variant having an id is not enough for ActiveResource to think the resource is not new.

shopify CLI, OSX 10.8 and Net::HTTP SSL Failure

Hi,

A recently setup development on OSX 10.8.2, using Ruby 1.9.3-p194 and 1.9.3-p286 and the shopify_api gem 3.0.2.

Whenever I setup a CLI shop with API credentials, any commands fail after 30 seconds with Net:HHTP errors complaining about SSL timeouts.

It seems my OSX OpenSSL version 1.0.1c and Ruby do not play nice. Nor do a bunch of other configurations. My old OSX 10.6 works fine though through using OpenSSL 0.9.8

I understand this may be unrelated to Shopify directly, but is there any expertise and experience at Shopify with a workaround for this glitch.

Failed to save a ShopifyAPI::Metafield in Rails 3.1

Hello;

I'm writing an app that create/update product metafields. It's written with Rails 3.1, but I have found and issue with Rails serialization method and Metafields fields.

If a create a metafield like:
m = ShopifyAPI::Metafield.new(:namespa => 'product', :key => key, :value_type => 'string', :value => value)

when try to serialize - which happens if a add it to a product with the add_metafield -
m.to_json

It fails with:
WARNING: DSL method ShopifyAPI::Metafield#namespace
no block given (yield)

This happens with when Metafield object get serialized inside active_model/serialization.rb, when serialization routine tries to create a hash with attributes and values:
Hash[(attribute_names + method_names).map { |n| puts n; [n, send(n)] }]

It seems that namespace attribute name of Metafields has a conflict becase as soon of:
send(n) # where n = 'namespace'

the error is raised
WARNING: DSL method ShopifyAPI::Metafield#namespace
no block given (yield)

Order Risks returning 500 error

I get a 500 when using shopify_api#master. Curl request gives "Database error". Any ideas?

curl -X POST -d "cause_cancel=false&display=true&message=test&recommendation=accept&score=0.1&source=external" -A "ShopifyAPI/3.2.0 ActiveResource/4.0.0 Ruby/2.0.0" -H "X-Shopify-Access-Token:REDACTED" https://my-store-name.myshopify.com/admin/orders/{{order_id}}/risks.json

Response:
{"errors":"Database error"}

Rails 4.1 compatibility?

When used in conjunction with shopify_app I get the following error when trying to log into the app:

Completed 500 Internal Server Error in 1ms

NoMethodError (undefined method `site' for "#<ShopifyAPI::Session:0x00000101cb5a28>":String):
  shopify_api (3.2.1) lib/shopify_api/resources/base.rb:52:in `activate_session'

Is the current version of the gem incompatible with rails 4.1?

shop_url

Hello. It is said in second step:
For a private App you just need to set the base site url as follows:
shop_url = "https://#{API_KEY}:#{PASSWORD}@SHOP_NAME.myshopify.com/admin"
ShopifyAPI::Base.site = shop_url

Would you please let me know, where do I define it? Do I create a separate .rb file in initializers or it has to be done somewhere else?

Thank you!

This library is not thread safe

With the increasing popularity of multi-threaded hosts, such as sidekiq and puma, plus the addition of rails 4.0 defaulting to thread-safe mode, it is becoming a limiting factor that this library is not thread safe.

The use of a class variable to store the site and auth token mean that if there are any concurrent requests on different threads these values will be overwritten and chaos may ensue.

I want to raise this issue here also because it has taken quite a while to figure out if the library is thread safe or not - and it's not an easy thing to test reliably. The best I can find is this post: http://ecommerce.shopify.com/c/shopify-apis-and-technology/t/threadsafety-shopify-api-gem-115828 . Reviewing the code and recent changes I believe the issue is still present.

A possible solution could be similar to the answer given in this question, and I'd like to know if this is applicable and a good idea for this library: http://stackoverflow.com/questions/8088126/is-it-thread-safe-to-set-active-resource-http-authentication-on-a-per-user-basis

edited: removed uncertainty - this library is not thread safe. As mentioned in comments ActiveResource has been updated so that the headers are now thread safe, however the session object and base.rb monkey patching still expose the issue.

Shopify::Metafield.all doesn't return all of a shop's metafields

Calling

irb(main):030:0> m = ShopifyAPI::Metafield.all

Returns

=> #<ActiveResource::Collection:0x007f84c8e6ce50 @elements=[#<ShopifyAPI::Metafield:0x007f84c8e6cd38 @attributes={"created_at"=>"2011-05-01T21:02:41-07:00", "description"=>nil, "id"=>:id, "key"=>"category", "namespace"=>"shopify-contest", "owner_id"=>:owner_id, "updated_at"=>"2011-05-01T21:02:41-07:00", "value"=>"other", "value_type"=>"string", "owner_resource"=>"shop"}, @prefix_options={}, @persisted=true>, #<ShopifyAPI::Metafield:0x007f84c8e77f30 @attributes={"created_at"=>"2011-05-01T21:02:41-07:00", "description"=>nil, "id"=>:id, "key"=>"join", "namespace"=>"shopify-contest", "owner_id"=>:owner_id, "updated_at"=>"2011-05-01T21:02:41-07:00", "value"=>"1", "value_type"=>"integer", "owner_resource"=>"shop"}, @prefix_options={}, @persisted=true>], @resource_class=ShopifyAPI::Metafield, @original_params={}>

But neither of those Metafields are this metafield, which most definitely exists in my store:

belmondo organic skin care pages water skincare products shopify

Am I missing something, or is this broken?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.