2
votes

I've got a model show, and I've got a model episode. A show has many episodes as you might imagine. I've got friendlyID configured and within the episode model:

friendly_id :slug_candidates, use: :slugged, :use => :scoped, :scope => :show

I imagine that the problem I'm having is due to me not working with the resource scope within Active Admin and not customizing the nested resource retrieval, but I'm uncertain how to do that: here's what happens.

Let's say I have a show named 'Show 1' and I create an episode with 'Episode 1' as the title. When I create a new show and have 'Episode 1' inside 'Show 2' it should be able to save since it's scoped to the show title.

2014-02-07T00:38:28.009413+00:00 app[web.1]:   Parameters: {"utf8"=>"✓", "authenticity_token"=>"yhP8K6jUVhWHHzqWhXvaABXDzh8eACYcHhkEhMKJt+8=", "show"=>{"creator_id"=>"132", "title"=>"Menuda Noche", "subtitle"=>"", "description"=>"", "position"=>"", "age_range"=>"", "single"=>"0", "skiplist"=>"0", "promote"=>"0", "approved"=>"1", "created_at(1i)"=>"", "created_at(2i)"=>"", "created_at(3i)"=>"", "created_at(4i)"=>"", "created_at(5i)"=>"", "updated_at(1i)"=>"", "updated_at(2i)"=>"", "updated_at(3i)"=>"", "updated_at(4i)"=>"", "updated_at(5i)"=>"", "episodes_attributes"=>{"1391733477006"=>{"episode"=>"1", "title"=>"Episode 1", "description"=>"", "duration"=>"6:11", "age_range"=>"", "embed_id"=>"3", "video"=>"b3f85199", "approved"=>"1", "tag_list"=>""}}, "channel_ids"=>["", "3"]}, "commit"=>"Create Show"}
2014-02-07T00:38:28.089273+00:00 app[web.1]: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_episodes_on_slug"
2014-02-07T00:38:28.089273+00:00 app[web.1]: DETAIL:  Key (slug)=(episode-1) already exists.
2014-02-07T00:38:28.093312+00:00 app[web.1]: Completed 500 Internal Server Error in 84ms
2014-02-07T00:38:28.099544+00:00 app[web.1]: ActiveRecord::RecordNotUnique (PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_episodes_on_slug"

My question then is this: what do I have to do within the admin/show.rb or admin/episode.rb to not only allow the saving of an episode with an already used title across shows but unique to that show, and how do I retrieve it as well?

Update

I'm still trying to figure out where I should override the create / update method; since I'm using the admin/show controller to create a new show and nested episodes, I'm guessing I have to override it there, but I'm still not clear on this:

Within admin/show.rb I put this in:

controller do
    def find_resource
        scoped_collection.friendly.find(params[:id])
    end
    def create
        puts "  ACCCCCTTTIVE AADDDDMMMIIIN CREEEEATTTTTTE "
        params.inspect
    end
end

Which of course STOPS anything from saving but I thought it would be a good dumb test. I then commented that out and put in something similar in the admin/episode.rb but it never seems to get called -- letting me think that the episode.rb save functions don't happen there...

Started POST "/admin/shows" for 127.0.0.1 at 2014-02-06 23:03:57 -0500
Processing by Admin::ShowsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"S5sXpSWZCLG3lg3x2QSw9p1xuHyGxIJndAqYWQWrC40=", "show"=>{"creator_id"=>"1", "title"=>"new new new", "subtitle"=>"sdf", "description"=>"", "position"=>"", "age_range"=>"", "single"=>"0", "skiplist"=>"0", "promote"=>"0", "approved"=>"0", "created_at(1i)"=>"", "created_at(2i)"=>"", "created_at(3i)"=>"", "created_at(4i)"=>"", "created_at(5i)"=>"", "updated_at(1i)"=>"", "updated_at(2i)"=>"", "updated_at(3i)"=>"", "updated_at(4i)"=>"", "updated_at(5i)"=>"", "episodes_attributes"=>{"1391745822502"=>{"episode"=>"", "title"=>"Part 1", "description"=>"", "duration"=>"", "age_range"=>"", "embed_id"=>"1", "video"=>"1234", "approved"=>"0", "tag_list"=>""}}, "channel_ids"=>[""]}, "commit"=>"Create Show"}
  AdminUser Load (38.1ms)  SELECT "admin_users".* FROM "admin_users" WHERE "admin_users"."id" = 1 ORDER BY "admin_users"."id" ASC LIMIT 1
   (149.2ms)  BEGIN
  Show Exists (18.7ms)  SELECT 1 AS one FROM "shows" WHERE "shows"."slug" = 'new-new-new' LIMIT 1
  Episode Exists (23.1ms)  SELECT 1 AS one FROM "episodes" WHERE "episodes"."show_id" IS NULL AND "episodes"."slug" = 'part-1' LIMIT 1
  SQL (205.8ms)  INSERT INTO "shows" ("age_range", "approved", "created_at", "creator_id", "description", "promote", "single", "skiplist", "slug", "subtitle", "title", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) RETURNING "id"  [["age_range", ""], ["approved", false], ["created_at", Thu, 06 Feb 2014 23:03:57 EST -05:00], ["creator_id", 1], ["description", ""], ["promote", false], ["single", false], ["skiplist", false], ["slug", "new-new-new"], ["subtitle", "sdf"], ["title", "new new new"], ["updated_at", Thu, 06 Feb 2014 23:03:57 EST -05:00]]
  SQL (22.4ms)  INSERT INTO "episodes" ("age_range", "approved", "created_at", "description", "duration", "embed_id", "show_id", "slug", "title", "updated_at", "video") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id"  [["age_range", ""], ["approved", false], ["created_at", Thu, 06 Feb 2014 23:03:57 EST -05:00], ["description", ""], ["duration", ""], ["embed_id", "1"], ["show_id", 188], ["slug", "part-1"], ["title", "Part 1"], ["updated_at", Thu, 06 Feb 2014 23:03:57 EST -05:00], ["video", "1234"]]
PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_episodes_on_slug"
DETAIL:  Key (slug)=(part-1) already exists.
: INSERT INTO "episodes" ("age_range", "approved", "created_at", "description", "duration", "embed_id", "show_id", "slug", "title", "updated_at", "video") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11) RETURNING "id"
   (1.6ms)  ROLLBACK
Completed 500 Internal Server Error in 573ms

PG::UniqueViolation - ERROR:  duplicate key value violates unique constraint "index_episodes_on_slug"
DETAIL:  Key (slug)=(part-1) already exists.

Update #2

Still a bit confused; I can see that it's breaking within admin/show in the controller do / def create, but I can't figure out how best to halt what was an automatic process of saving the show and nested episodes.

Show Exists (4.3ms)  SELECT 1 AS one FROM "shows" WHERE "shows"."slug" = 'blah-black' LIMIT 1
Episode Exists (2.5ms)  SELECT 1 AS one FROM "episodes" WHERE "episodes"."show_id" IS NULL AND "episodes"."slug" = 'part-1' LIMIT 1
Episode Exists (2.9ms)  SELECT 1 AS one FROM "episodes" WHERE "episodes"."show_id" IS NULL AND "episodes"."slug" = 'part-2' LIMIT 1

Since episodes are under show, it still seems this should be distinct as there are no other shows with these episode names that have a null id.

The only other thing I can think of is manually doing this: first saving a show, getting a show_id, then attempting to save each nested episode with that show_id, but not sure if I'm thinking about this correctly...

3

3 Answers

1
votes
PG::UniqueViolation - ERROR:  duplicate key value violates unique constraint "index_episodes_on_slug"

It looks like this error is coming from your database and not active admin. You might need to change the unique index in your migration to include the show_id.

So in your migration instead of:

add_index :episodes, :slug, :unique => true

You should have something like

add_index :episodes, [:show_id, :slug], :unique => true
0
votes

Have you considered using a belongs_to?

app/admin/shows.rb:

ActiveAdmin.register Show do
  ...
end

app/admin/episodes.rb:

ActiveAdmin.register Episode do
  belongs_to :show
  ...
end

ActiveAdmin will register nested routes for your resources, ala:

http://server.com/shows/1/episodes/2
0
votes

app/models/episode.rb:

class Episode < ActiveRecord::Base
  ....
  friendly_id :title, :use => [:slugged, :scoped], :scope => :show
  ....
end

app/admin/episodes.rb:

ActiveAdmin.register Episode do
  belongs_to :show, :optional => true
  ...
end

Worked fine for me.