Skip to content

Commit

Permalink
Add foreign key option to Fields (#807)
Browse files Browse the repository at this point in the history
* Add foreign key option to assosiations Fields
* Add country code to customers in example_app to show how it works
  • Loading branch information
Yaroslav Litvinov authored and nickcharlton committed Jul 31, 2017
1 parent 190cfe5 commit 736266d
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 28 deletions.
10 changes: 10 additions & 0 deletions docs/customizing_dashboards.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,16 @@ which are specified through the `.with_options` class method:

`:direction` - What direction the sort should be in, `:asc` (default) or `:desc`.

`:primary_key` - Specifies object's primary_key. Defaults to `:id`.

`:foreign_key` - Specifies the name of the foreign key directly. Defaults to `:#{attribute}_id`

**Field::BelongsTo**

`:primary_key` - Specifies object's primary_key. Defaults to `:id`.

`:foreign_key` - Specifies the name of the foreign key directly. Defaults to `:#{attribute}_id`

**Field::Number**

`:decimals` - Set the number of decimals to display. Defaults to `0`.
Expand Down
4 changes: 4 additions & 0 deletions lib/administrate/field/associative.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def associated_class_name
def primary_key
options.fetch(:primary_key, :id)
end

def foreign_key
options.fetch(:foreign_key, :"#{attribute}_id")
end
end
end
end
2 changes: 1 addition & 1 deletion lib/administrate/field/belongs_to.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def self.permitted_attribute(attr)
end

def permitted_attribute
self.class.permitted_attribute(attribute)
foreign_key
end

def associated_resource_options
Expand Down
10 changes: 5 additions & 5 deletions lib/administrate/field/deferred.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ def searchable?
options.fetch(:searchable, deferred_class.searchable?)
end

delegate(
:html_class,
:permitted_attribute,
to: :deferred_class,
)
def permitted_attribute(attr)
options.fetch(:foreign_key, deferred_class.permitted_attribute(attr))
end

delegate :html_class, to: :deferred_class
end
end
end
20 changes: 20 additions & 0 deletions spec/example_app/app/dashboards/country_dashboard.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require "administrate/base_dashboard"

class CountryDashboard < Administrate::BaseDashboard
ATTRIBUTES = %i(code name).freeze

ATTRIBUTE_TYPES = {
created_at: Field::DateTime,
updated_at: Field::DateTime,
code: Field::String,
name: Field::String,
}.freeze

COLLECTION_ATTRIBUTES = ATTRIBUTES
FORM_ATTRIBUTES = ATTRIBUTES
SHOW_PAGE_ATTRIBUTES = ATTRIBUTES

def display_resource(resource)
resource.name
end
end
3 changes: 3 additions & 0 deletions spec/example_app/app/dashboards/customer_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class CustomerDashboard < Administrate::BaseDashboard
orders: Field::HasMany.with_options(limit: 2),
updated_at: Field::DateTime,
kind: Field::Select.with_options(collection: Customer::KINDS),
country: Field::BelongsTo.
with_options(primary_key: :code, foreign_key: :country_code),
}

COLLECTION_ATTRIBUTES = ATTRIBUTE_TYPES.keys
Expand All @@ -19,6 +21,7 @@ class CustomerDashboard < Administrate::BaseDashboard
:email,
:email_subscriber,
:kind,
:country,
].freeze

def display_resource(customer)
Expand Down
3 changes: 3 additions & 0 deletions spec/example_app/app/models/country.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class Country < ActiveRecord::Base
validates :code, :name, presence: true
end
1 change: 1 addition & 0 deletions spec/example_app/app/models/customer.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class Customer < ActiveRecord::Base
has_many :orders, dependent: :destroy
belongs_to :country, foreign_key: :country_code, primary_key: :code

validates :name, presence: true
validates :email, presence: true
Expand Down
11 changes: 11 additions & 0 deletions spec/example_app/db/migrate/20170510122301_create_countries.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
class CreateCountries < ActiveRecord::Migration[4.2]
def change
create_table :countries do |t|
t.string :code, null: false, index: { unique: true }
t.string :name

t.timestamps null: false
end
add_column :customers, :country_code, :string, index: true
end
end
22 changes: 16 additions & 6 deletions spec/example_app/db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema.define(version: 20170508183744) do
ActiveRecord::Schema.define(version: 20170510122301) do

# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
Expand All @@ -23,13 +23,23 @@
t.datetime "updated_at", null: false
end

create_table "customers", id: :serial, force: :cascade do |t|
t.string "name", null: false
t.string "email", null: false
create_table "countries", force: :cascade do |t|
t.string "code", null: false
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "email_subscriber"
t.string "kind", default: "standard", null: false
end

add_index "countries", ["code"], name: "index_countries_on_code", unique: true, using: :btree

create_table "customers", force: :cascade do |t|
t.string "name", null: false
t.string "email", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.boolean "email_subscriber"
t.string "kind", default: "standard", null: false
t.string "country_code"
end

create_table "delayed_jobs", id: :serial, force: :cascade do |t|
Expand Down
28 changes: 20 additions & 8 deletions spec/example_app/db/seeds.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,40 @@
Product.destroy_all
ProductMetaTag.destroy_all
Series.destroy_all
Country.destroy_all

100.times do
countries = Country.create! [
{ code: "US", name: "USA" },
{ code: "CA", name: "Canada" },
{ code: "CN", name: "China" },
{ code: "RU", name: "Russia" },
{ code: "AU", name: "Australia" },
]

customer_attributes = Array.new(100) do
name = "#{Faker::Name.first_name} #{Faker::Name.last_name}"
Customer.create(
{
name: name,
email: Faker::Internet.safe_email(name),
)
country: countries.sample,
}
end

customers = Customer.create!(customer_attributes)

product_attributes = YAML.load_file(Rails.root.join('db/seeds/products.yml'))

product_attributes.each do |attributes|
attributes = attributes.merge product_meta_tag_attributes: {
meta_title: Faker::LordOfTheRings.character,
meta_description: Faker::LordOfTheRings.location,
}
Product.create attributes.merge(price: 20 + rand(50))
Product.create! attributes.merge(price: 20 + rand(50))
end

Customer.all.each do |customer|
customers.each do |customer|
(1..3).to_a.sample.times do
order = Order.create(
order = Order.create!(
customer: customer,
address_line_one: Faker::Address.street_address,
address_line_two: Faker::Address.secondary_address,
Expand All @@ -44,7 +56,7 @@

item_count = (1..3).to_a.sample
Product.all.sample(item_count).each do |product|
LineItem.create(
LineItem.create!(
order: order,
product: product,
unit_price: product.price,
Expand All @@ -54,4 +66,4 @@
end
end

Series.create(name: "An example")
Series.create!(name: "An example")
16 changes: 14 additions & 2 deletions spec/lib/fields/belongs_to_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
Foo = Class.new
allow(Foo).to receive(:all).and_return([])

association = Administrate::Field::BelongsTo.
with_options(class_name: "Foo")
association = Administrate::Field::BelongsTo.with_options(
class_name: "Foo",
)
field = association.new(:customers, [], :show)
candidates = field.associated_resource_options

Expand Down Expand Up @@ -67,6 +68,17 @@
end
end

describe "foreign_key option" do
it "determines what foreign key is used on the relationship for the form" do
association = Administrate::Field::BelongsTo.with_options(
foreign_key: "foo_uuid", class_name: "Foo",
)
field = association.new(:customers, [], :show)
permitted_attribute = field.permitted_attribute
expect(permitted_attribute).to eq("foo_uuid")
end
end

describe "#resources" do
context "with `order` option" do
it "returns the resources in correct order" do
Expand Down
23 changes: 17 additions & 6 deletions spec/lib/fields/deferred_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@

describe Administrate::Field::Deferred do
describe "#permitted_attribute" do
it "delegates to the backing class" do
deferred = Administrate::Field::Deferred.new(Administrate::Field::String)
allow(Administrate::Field::String).to receive(:permitted_attribute)
context "when given a `foreign_key` option" do
it "returns the value given" do
deferred = Administrate::Field::Deferred.
new(Administrate::Field::BelongsTo.with_options(foreign_key: :bar))
expect(deferred.permitted_attribute(:foo)).to eq(:bar)
end
end

deferred.permitted_attribute(:foo)
context "when not given a `foreign_key` option" do
it "delegates to the backing class" do
deferred = Administrate::Field::Deferred.
new(Administrate::Field::String)
allow(Administrate::Field::String).to receive(:permitted_attribute)

expect(Administrate::Field::String).
to have_received(:permitted_attribute).with(:foo)
deferred.permitted_attribute(:foo)

expect(Administrate::Field::String).
to have_received(:permitted_attribute).with(:foo)
end
end
end

Expand Down

0 comments on commit 736266d

Please sign in to comment.