How to change a Phoenix Project name smoothly?

I use mix phoenix.new paper to create a new project paper.

So all the stuff is called Paper or :paper.

However, I have to define a model called paper. So I have something like defmodule Paper.Paper do.

When I have multiple aliaes, I need to move Paper.paper to the last.

I know I made a “stupid” codename that may interfere with the model name.

So how can I modify all the Paper. stuff and :paper stuff eaisly? Is there a Phoenix mix command to do that?

Thanks!

9 Likes

There is not a command for renaming a project. I have however had to do so a couple times in the past, and in general global find and replace works really rather well. Just also move any directories named paper and you’re done.

5 Likes

Thanks a lot! I just want to know if others may have the same problem. In my following project I should be more careful about the namings.

2 Likes

A global find+replace works a lot better in Elixir than in most OOP-languages, because you always refer to a certain piece of code the same way: ModuleName.function_name. And structs use the ModuleName as well.

In OOP-languages, you can only hope that some object isn’t referred to under a different name.

4 Likes

I’ve been using this script for the two or three times I had to rename a phoenix project: https://gist.github.com/nerdyworm/3d623b13bf0d6d664373e2f501f16423

requires ack to be installed, but you could certainly swap that out for grep.

Cheers,
Ben

12 Likes

• Works on MacOS, not tested elsewhere.
• Needs: git, xargs and sed.

From the root folder of the project:

  1. git grep -l 'old_name' | xargs sed -i '' -e 's/old_name/new_name/g'

  2. git grep -l 'OldName' | xargs sed -i '' -e 's/OldName/NewName/g'

  3. mv ./lib/old_name ./lib/new_name

  4. mv ./lib/old_name.ex ./lib/new_name.ex

    If you have a similar folder structure in the tests folder, you probably also need:

  5. mv ./test/old_name ./test/new_name

11 Likes

@jaysoifer: you forgot about mv command for tests :smile:
Also you need to be careful using grep (no preview of changes), because some simple names could be also in other files like assets. Better way is to exclude some folders - just to be sure.
I suggest to use kfilereplace if you are using KDE/Plasma 5, because you can preview what files will be modified.

2 Likes

Editing!

I’m running 1.3-rc1, I don’t see anything else missing, can you help me?

@jaysoifer: you could have same directory structure in test folder like in lib folder.

Updated!

I am working on phoenix 1.3.0 , is possible to use the above command to change project name?

1 Like

Will this work for Phoenix 1.3?

1 Like
mv ./lib/old_name_web ./lib/new_name_web
mv ./lib/old_name_web.ex ./lib/new_name_web.ex

…done

Since this is the first hit on google for this problem, I library that I’ve used a couple times for this problem is

3 Likes

Great library! Worked out great, the only was with it also change the DB name on dev.exs/text.exs etc which I had to fix manually but besides that - works great!

1 Like

While I do love elixir, it’s the wrong tool for this job. I’m replying to the topic so the next time I google how to rename a project, I’ll find this code here ready to copy and paste.

Now, you might notice this code is pretty #^@!. I didn’t write it. I though it would be fun to see how well AI could do a pretty simple awk/sed/mv/bash script. And 3 hours later I realize:

  1. Reading the man page for awk/sed/find/etc is faster than asking AI to do it
  2. I have zero fear that Skynet will kill all humans. It would bring nerf guns to the fight at best.
  3. I have 99.9% fear that some programmer will ask AI to write the login page for my bank, or worse.

But in AI’s defense:

  1. I have written worse code than the following
  2. it does appear to have worked.
  3. It comments more than I do
  4. It spells and talks the English much better than I

Warning: It will rename the DB in config/dev.ex too.

#!/bin/bash

OLD_PROJECT_PASCAL_NAME=OldeProject
NEW_PROJECT_PASCAL_NAME=WorldProject
OLD_PROJECT_SNAKE_NAME=olde_project
NEW_PROJECT_SNAKE_NAME=world_project

# Function to rename directories
rename_directories() {
    find . -depth -type d -name "*$OLD_PROJECT_SNAKE_NAME*" -exec bash -c 'dir="$1" && newdir="${dir//'"$OLD_PROJECT_SNAKE_NAME"'/'"$NEW_PROJECT_SNAKE_NAME"'}" && [ "$dir" != "$newdir" ] && mv "$dir" "$newdir"' _ {} \;
}

# Function to rename files
rename_files() {
    find . -type f \( -name "*.$1" -o -name "*.$2" -o -name "*.$3" -o -name "*.$4" \) -exec bash -c 'file="$1" && newfile="${file//'"$OLD_PROJECT_SNAKE_NAME"'/'"$NEW_PROJECT_SNAKE_NAME"'}" && [ "$file" != "$newfile" ] && mv "$file" "$newfile"' _ {} \;
}

# Function to update contents inside files
update_file_contents() {
    find . -type f \( -name "*.$1" -o -name "*.$2" -o -name "*.$3" -o -name "*.$4" \) -exec sed -i -e "s/${OLD_PROJECT_PASCAL_NAME}/${NEW_PROJECT_PASCAL_NAME}/g" -e "s/${OLD_PROJECT_SNAKE_NAME}/${NEW_PROJECT_SNAKE_NAME}/g" {} +
}

# Rename directories
rename_directories
# Rename files
rename_files "ex" "exs" "eex" "md"
# Update contents inside files
update_file_contents "ex" "exs" "eex" "md"

echo "Project successfully renamed from ${OLD_PROJECT_PASCAL_NAME} to ${NEW_PROJECT_PASCAL_NAME} and ${OLD_PROJECT_SNAKE_NAME} to ${NEW_PROJECT_SNAKE_NAME}."

I’ve been using the exact code from this earlier post in this thread and it still works fine on 1.17.

I had some free time. (Still the holidays). Script uses POSIX commands so it should work on every OS that I care about.

Just run:

wget https://raw.githubusercontent.com/blackham/rename_elixir_app/main/rename.sh
chmod +x rename.sh
./rename.sh NewProjectName

If you have a funky project name and want to force the snake_case name
./rename.sh NewIM new_im

1 Like

Oh! My bad, I didn’t look closely at what you did.

This is definitly a step up.