简体   繁体   中英

How to make rails resource ids non-unique for every user?

Let's say I have a rails app for users to manage tasks. So when the user 1 creates a task, it will have the following URL:

user/task/1

Now another user (#2) creates a new task and it will look like:

user/task/2

If the first user will create add another one it will have the number 3. And so on. The new task will not reflect the amount of tasks a user has, but the amount of resources that is stored in my database.

I would like to have every user create tasks without seeing how many tasks are in the system in total. So everybody could have task 1,2,3.. as well as tasklist 1,2,3..

I guess one way to go is to have a new custom kind of ID and try to put it into the URL. Am I close? Maybe there's a good guide/a better way?

Thanks

If I understand what you want to accomplish, I would do this:

In your task model, I would add:

  1. Add a belongs_to for the user
  2. Add a integer column called user_specific_identifier

Then in the controller make sure to scope the queries to use the user:

def index
  @tasks = Task.where(user: current_user)
               .where(user_specific_identifier: params[:id])
  # ...
end

You might be able to use to_param to get your helpers to work properly by overriding what rails uses as the ID for that model. However I have not done this in cases where the ID is not unique.

You might want to checkout RailsCast #314 Pretty URLs with FriendlyId .

The easiest way to do this would be to keep an ordinal on the user record which is incremented when you need a new task ID. Then, you will store this ID on the task, and override #to_param on your Task model, so that Rails' URL helpers will use it for URL generation.

So, you'll need a migration:

add_column :users, :task_count, :integer
add_index  :users, :task_count, unique: true

add_column :tasks, :user_task_id, :integer
add_index  :tasks, :user_task_id, unique: true

Then add a before_create filter on your Task model:

# Task
before_create :set_user_specific_id
def set_user_specific_id
  self.user_task_id = self.user.get_next_task_id!
end

def to_param
  self.user_task_id
end

# User
def get_next_task_id!
  # Atomic increment is used here to prevent race conditions from generating dupe IDs
  increment_counter :task_count
  reload
  self.task_count
end

Now you can use your URL helpers like user_task_path(user, task) to generate URLs that use the user-specific ID, rather than the actual row ID. Your finder would then be something like Task.where(user_id: params[:user_id], user_task_id: params[:id]) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM