1
votes

I'm new to Spreecommerce and am having trouble creating a product with a custom attribute 'delivery_on' via the admin interface. In short, I create the migrate, the product_decorator.rb, add the new attribute to the permitted attributes, create a deface file for the admin pages. However, I get an error message stating "Delivery on can't be blank" when I try to create a new product via the admin interface.

Many thanks in advance for any help!

I'm using ruby 2.2.1, rails 4.2.3 and the following spree gems:

gem 'spree_core',             branch: '3-0-stable'
gem 'spree_api',              branch: '3-0-stable'
gem 'spree_backend',          branch: '3-0-stable'
gem 'spree_gateway',          github: 'spree/spree_gateway', branch: '3-0-stable'
gem 'devise'

Steps to reproduce

  • Create a migration rails g migration add_delivery_on_to_spree_products
  • In the migration file YYYYMMDDHHMMSS_add_delivery_on_to_spree_products, insert changes to 'change' method:

    def change
      add_column :spree_products, :delivery_on, :date
      add_index :spree_products, :delivery_on
    end
    
  • Run bundle exec rake db:migrate and it adds the attributes to the spree_products table but it doesn't update the scheema.rb
  • Run rake db:migrate:reset and it updated the schema. But it wipes out the db first. Not sure this is the ideal way to do it (followed the guidance on this stackoverflow thread)

  • In the app/models/spree folder, create a 'product_decorator.rb' file and add

    Spree::Product.class_eval do
      validates :delivery_on, presence: true
      delegate_belongs_to :master, :delivery_on, :active
    end
    
  • In app/controllers/application_controllers.rb, add

    Spree::PermittedAttributes.product_attributes << :delivery_on
    Spree::Api::ApiHelpers.product_attributes << :delivery_on
    
  • In app/overrides/spree, create deface file 'add_delivery_on_to_product_new':

    Deface::Override.new(:virtual_path => 'spree/admin/products/new',
      :name => 'add_delivery_on_to_product_new',
      :original => '931806c52c232e6a373cb06fa739f3913ad13c3d',
      :insert_after => "erb[loud]:contains('text_field :available_on')",
      :text => "
        <%= f.field_container :delivery_on, class: ['form-group'] do %>
          <%= f.label :delivery_on, raw(Spree.t(:delivery_on) + content_tag(:span, ' *')) %>
          <%= f.error_message_on :delivery_on %>
          <%= f.text_field :delivery_on, :class => 'datepicker form-control' %>
        <% end %>
      ")
    
  • In app/overrides/spree, create deface file 'add_delivery_on_to_product_form':

    Deface::Override.new(:virtual_path => 'spree/admin/products/_form',
      :name => 'add_delivery_on_to_product_edit',
      :original => '931806c52c232e6a373cb06fa739f3913ad13c3d',
      :insert_after => "erb[loud]:contains('text_field :available_on')",
      :text => "
        <%= f.field_container :delivery_on, class: ['form-group'] do %>
          <%= f.label :delivery_on, raw(Spree.t(:delivery_on) + content_tag(:span, ' *')) %>
          <%= f.error_message_on :delivery_on %>
          <%= f.text_field :delivery_on, :value =>
    datepicker_field_value(@product.delivery_on), class: 'datepicker form-control' %>
        <% end %>
      ")
    
  • Go to localhost:3000/admin and try to create a new product, but I get an error message stating "Delivery on can't be blank."

  • Here is the output in the logs

    Started POST "/admin/products" for ::1 at 2015-09-14 22:24:20 +0200 Processing by Spree::Admin::ProductsController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"O6BkeJEhquvCnu5nrIHwYYUZqkif8C9MqKRf4+qvjxH5UqkM9m+QDwvxcfBFqE4QcwPnDU/wrwAKGyk+wzVz8Q==", "product"=>{"name"=>"test", "sku"=>"123", "prototype_id"=>"", "price"=>"99", "available_on"=>"2015/09/12", "delivery_on"=>"2015/09/30", "shipping_category_id"=>"1"}, "button"=>""} Spree::Preference Load (0.1ms) SELECT "spree_preferences".* FROM "spree_preferences" WHERE "spree_preferences"."key" = ? LIMIT 1 [["key", "spree/backend_configuration/locale"]] User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] (0.1ms) SELECT COUNT(*) FROM "spree_roles" INNER JOIN "spree_roles_users" ON "spree_roles"."id" = "spree_roles_users"."role_id" WHERE "spree_roles_users"."user_id" = ? AND "spree_roles"."name" = ? [["user_id", 1], ["name", "admin"]] (0.2ms) begin transaction Spree::Product Exists (1.1ms) SELECT 1 AS one FROM "spree_products" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "spree_products"."id" AND "friendly_id_slugs"."deleted_at" IS NULL AND "friendly_id_slugs"."sluggable_type" = ? WHERE ("spree_products"."id" IS NOT NULL) AND "spree_products"."slug" = 'test' LIMIT 1 [["sluggable_type", "Spree::Product"]] Spree::Product Exists (0.2ms) SELECT 1 AS one FROM "spree_products" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "spree_products"."id" AND "friendly_id_slugs"."deleted_at" IS NULL AND "friendly_id_slugs"."sluggable_type" = ? WHERE ("spree_products"."id" IS NOT NULL) AND "spree_products"."slug" = 'test-123' LIMIT 1 [["sluggable_type", "Spree::Product"]] Spree::Product Exists (0.5ms) SELECT 1 AS one FROM "spree_products" INNER JOIN "friendly_id_slugs" ON "friendly_id_slugs"."sluggable_id" = "spree_products"."id" AND "friendly_id_slugs"."deleted_at" IS NULL AND "friendly_id_slugs"."sluggable_type" = ? WHERE ("spree_products"."id" IS NOT NULL) AND ("friendly_id_slugs"."sluggable_type" = 'Spree::Product' AND "friendly_id_slugs"."slug" = 'test-123') LIMIT 1 [["sluggable_type", "Spree::Product"]] Spree::Variant Exists (0.5ms) SELECT 1 AS one FROM "spree_variants" WHERE "spree_variants"."sku" = '123' AND "spree_variants"."deleted_at" IS NULL LIMIT 1 Spree::Product Exists (0.1ms) SELECT 1 AS one FROM "spree_products" WHERE "spree_products"."slug" = 'test-123' LIMIT 1 (0.1ms) rollback transaction

Gemfile

source 'https://rubygems.org'
ruby '2.2.1'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails',                  '4.2.3'
# Use SCSS for stylesheets
gem 'sass-rails',             '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier',               '>= 1.3.0'
# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails',           '~> 4.1.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder',               '~> 2.0'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc',                   '~> 0.4.0', group: :doc

gem 'spree_core',             branch: '3-0-stable'
gem 'spree_api',              branch: '3-0-stable'
gem 'spree_backend',          branch: '3-0-stable'
gem 'spree_gateway',          github: 'spree/spree_gateway', branch: '3-0-stable'
gem 'devise'

# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Unicorn as the app server
# gem 'unicorn'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug'
  # Use sqlite3 as the database for Active Record
  gem 'sqlite3'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  # Access an IRB console on exception pages or by using <%= console %> in views
  gem 'web-console',          '~> 2.0'
end

group :production do
  # Use PostgreSQL as the database for Active Record
  gem 'pg',                   '0.18.2'
  # Use rails_12 factor to enable serving assets in production and setting your logger to standard out.
  gem 'rails_12factor',       '0.0.3'
end
1
Your migration is adding an active column, not a delivery_on column -- did you paste the right migration?Mike Manfrin
Good catch. I copied the wrong migration initially. Updated the post with the right migration. Thanks @MikeManfrinjayd
I believe you need to add delivery_on to your controller's strong params; likely it's not being permitted through and so the app is trying to make a product without a delivery on date (which is causing your validation to fail).Mike Manfrin
@MikeManfrin I thought there was an issue with strong params as well. I found this thread on github from spree contributors and followed their solution. In my post, see the part about adding delivery_on to PermittedAttributes in app/controllers/application_controllers.rb. When I start up the console and run Spree::PermittedAttributes.product_attributes, delivery_on is returned in the list of permitted attributes so I believe it's been added. Any other ideas? Appreciate the help.jayd

1 Answers

0
votes

I removed

delegate_belongs_to :product, :delivery_on

from my product_decorator.rb file and that solved the problem.

To be honest, I didn't really understand what delegate_belongs_to does but I added it because the official Spree deface overrides tutorial instructs us to do so:

We also need to delegate sale_price to the master variant in order to get the updated product edit form working.

We can do this by creating a new file app/models/spree/product_decorator.rb and adding the following content to it:

module Spree Product.class_eval do delegate_belongs_to :master, :sale_price end end

Note, I tried with delegate_belongs_to :master, :delivery_on as well but that didn't work either.