Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use participatory spaces slugs in URLs #1842

Merged
merged 17 commits into from
Sep 19, 2017
Merged

Conversation

mrcasals
Copy link
Contributor

@mrcasals mrcasals commented Sep 14, 2017

🎩 What? Why?

Use process and assemblies slugs in URLs.

📌 Related Issues

📋 Subtasks

  • Use process slugs in URLs
  • Use assembly slugs in URLs
  • Redirect old URLs with IDs to the new ones using the slugs
  • Fix specs
  • Validate slug format in model?

@mrcasals mrcasals self-assigned this Sep 14, 2017
@ghost ghost added the in-progress label Sep 14, 2017
@mrcasals
Copy link
Contributor Author

Currently, this solution doesn't work as I'd expect:

(note the menu highlighting)

I'll try to make a redirect when the param is an ID.

@codecov
Copy link

codecov bot commented Sep 14, 2017

Codecov Report

Merging #1842 into master will decrease coverage by 0.02%.
The diff coverage is 92.68%.

@@            Coverage Diff             @@
##           master    #1842      +/-   ##
==========================================
- Coverage    98.5%   98.47%   -0.03%     
==========================================
  Files        1127     1127              
  Lines       25284    25316      +32     
==========================================
+ Hits        24906    24931      +25     
- Misses        378      385       +7

@@ -30,7 +30,12 @@ def current_participatory_process(env, params)
end

def detect_current_participatory_process(params)
OrganizationParticipatoryProcesses.new(@organization).query.find_by_id(params["participatory_process_id"])
organization_processes.where(id: params["participatory_process_id"]).first ||
organization_processes.where(slug: params["participatory_process_id"]).first
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use ActiveRecord's OR?

@@ -42,7 +42,12 @@ def ability_context

def detect_participatory_process
request.env["current_participatory_process"] ||
OrganizationParticipatoryProcesses.new(current_organization).query.find(params[:participatory_process_id] || params[:id])
organization_processes.where(id: params[:participatory_process_id] || params[:id]).first ||
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

@deivid-rodriguez
Copy link
Contributor

@mrcasals No big deal but IMO redirecting is better than serving the same content for both URLs with a 200 response. Search engines don't like it when different URLs serve the same content.

get "/processes/:process_id/f/:feature_id", to: redirect { |params, _request|
process = Decidim::ParticipatoryProcess.where(id: params[:process_id]).first
process ? "/processes/#{process.slug}/f/#{params[:feature_id]}" : "/404"
}, constraints: { process_id: /[0-9]+/ }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrcasals Maybe you can use find(params[:process_id]) here. If the record is not found, an ActiveRecord::RecordNotFound error will be raised, which will result in a 404. I think that's better than manually redirecting to the "/404" page, since in that case the request will have a 200 status instead of a 404.

Also, to be technically correct, I guess this should be a fallback and the preferred routes should be matched first? I'm think of the super-unlikely case of numerical slugs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rails routes run the first definition that matches, so I need these redirections on top since they have the constraint.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I see. The other alternative would be to manually redirect from the controller instead. But numerical slugs is a small edge case anyways.

@mrcasals
Copy link
Contributor Author

@deivid-rodriguez good point. I added redirections in 09eb417 right before your comment, today I'll fix the /404 thing you point out 😄

@mrcasals mrcasals force-pushed the use-spaces-slug-in-urls branch 3 times, most recently from f3ee3a7 to b6c6dcb Compare September 18, 2017 08:32
@mrcasals mrcasals changed the title [WIP] Use process slugs in URLs Use participatory spaces slugs in URLs Sep 18, 2017
@@ -50,10 +50,14 @@ def scope
@scope ||= current_organization.scopes.where(id: scope_id).first
end

def to_param
id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This attribute is not defined, isn't it? I think you meant context[:assembly_id], right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was being used, actually, so 🔥

{ host: organization.host, foreign_key.to_sym => id }
{
host: organization.host,
"#{underscored_name}_slug".to_sym => slug
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such hack lol 😄

@@ -59,10 +59,14 @@ def participatory_process_group
Decidim::ParticipatoryProcessGroup.where(id: participatory_process_group_id).first
end

def to_param
id
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

@@ -14,14 +14,14 @@ class AdminEngine < ::Rails::Engine
paths["db/migrate"] = nil

routes do
resources :assemblies do
resources :assemblies, param: :slug, except: :show do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The param name slug why sometimes is called like this and sometimes like assembly_slug? Is it intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I simply renamed the old :id/:assembly_id to use the slug. I guess :assembly_id was used to differentiate assembly IDs from feature IDs. I don't want to change this because we might move features to use slugs in the URLs, so this is good.

@@ -15,7 +15,7 @@ class AdminEngine < ::Rails::Engine

routes do
resources :participatory_process_groups
resources :participatory_processes, except: :show do
resources :participatory_processes, param: :slug, except: :show do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto.

beagleknight
beagleknight previously approved these changes Sep 18, 2017
Copy link
Contributor

@josepjaume josepjaume left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job! 🎉

Can you add an entry on the CHANGELOG indicating we use slugs on URLs now, and also a note about redirects?

resources :assemblies, only: [:index, :show], path: "assemblies" do
get "assemblies/:assembly_id", to: redirect { |params, _request|
assembly = Decidim::Assembly.find(params[:assembly_id])
assembly ? "/assemblies/#{assembly.slug}" : "/404"
Copy link
Contributor

@deivid-rodriguez deivid-rodriguez Sep 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mrcasals Isn't this line dead code now? find either rises or returns a record. I don't think we need the manual "/404" redirection anymore?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: Not the whole line, just the "/404" branch.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rechecking this, the find method makes the constraint to fail, but I'm getting an authorization error instead of a nice 404 error:

I think I will go back to what we used to have, and then investigate again.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely unexpected... 🤔

I think I will go back to what we used to have, and then investigate again.

Agree on the approach 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, I misschecked it. This is why I'm getting with the current code:

The previous error appears after accessing a with a wrong slug: http://localhost:3000/assemblies/does-not-exist raises an authorization error instead of a 404.

I'll look into it, since it seems to be caused by this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, last commit should fix it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 If you want to test this stuff, I added some support for it a while ago. It's the a 404 page shared example.

Copy link
Contributor

@oriolgual oriolgual left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have format validations on the slug field to make sure we only accept valid chars (a-Z, 0-9 and - I guess)

CHANGELOG.md Outdated
@@ -6,6 +6,10 @@

- **decidim-proposals**: Hide proposal vote button when proposal is answered and rejected. [\#1861](https://github.com/decidim/decidim/pull/1861)

**Changed**

- **decidim**: URLs now use the participatory space slug instead of the URL, both in the public pages and in the admin. Old routes using the space IDs now redirect to the ones using the slug. [\#1842](https://github.com/decidim/decidim/pull/1842)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of the ID

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're not technically redirecting, only serving the same content (except for the participatory process and assembly page where we are indeed redirecting). There's a difference in terms of SEO, so I'd say "Old routes using the space IDs still serve the same content as the ones using the slug".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mh I think it's a proper redirection, sending a 301 HHTP status code:

http://guides.rubyonrails.org/routing.html#redirection

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried it and it working perfectly! I was probably just misreading the patch, sorry! 😊

@deivid-rodriguez
Copy link
Contributor

Did you notice this warning when seeding?

/home/deivid/Code/decidim/decidim-core/lib/decidim/participable.rb:12: warning: already initialized constant Decidim::Participable::SLUG_FORMAT

Also, can you generate a development app right now? I just had a dependency problem but I'm not sure if it's my environment...

OrganizationAssemblies.new(@organization).query.find_by_id(params["assembly_id"])
organization_assemblies.where(slug: params["assembly_slug"]).or(
organization_assemblies.where(id: params["assembly_id"])
).first!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is what confused me... Do we need the assembly_id part? I tried and the redirection seems to work fine without it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check it, sure!

@mrcasals
Copy link
Contributor Author

@deivid-rodriguez CircleCI has some problems:

Bundler::GitError: The git source https://github.com/rails/rails.git is not yet checked out. Please run `bundle install` before trying to start your application

I haven't generated the development app, let me check this tomorrow.

@deivid-rodriguez
Copy link
Contributor

I'm having a look at it and it seems like a problem most likely caused by #1845...

@josepjaume josepjaume merged commit 6ca97e1 into master Sep 19, 2017
@josepjaume josepjaume deleted the use-spaces-slug-in-urls branch September 19, 2017 12:33
@ghost ghost removed the in-review label Sep 19, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants