Как сделать так, чтобы в моем перенаправлении было указано имя вместо идентификатора? - PullRequest
0 голосов
/ 02 мая 2018

Я использую Rails 5.1. В моем контроллере я бы хотел перенаправить на мой метод "show", например,

redirect_to(@organization)

но я бы хотел, чтобы URL отображался как

/organization/organization_name

вместо

/organization/primary_key_id

Как мне это настроить? У меня уже есть поле "имя" в моей модели организации.

Редактировать: По запросу это метод индекса моего PagesController ...

class PagesController < ApplicationController

  # Should be the home page
  def index
    worker_id = params[:worker_id]
    worker = Worker.find_by_id(worker_id)
    if worker && worker.organization
      redirect_to(worker.organization)
    else
      render :file => "#{Rails.root}/public/404", layout: false, status: 404
    end
  end

end

Редактировать: Мой config/routes.rb файл

  resources :organizations, :only => [:show] do
    post :update_work
    get :get_work
    get :mine
    get :poll
    post :submit
    get :home
    get :terms_of_use
  end

Вот файл app/model/stratum_worker.rb

class StratumWorker < ApplicationRecord

  has_one :organization_worker
  has_one :organization, :through => :organization_worker

Ответы [ 4 ]

0 голосов
/ 09 мая 2018

Я написал пост здесь , подробно описывающий это некоторое время назад. Большая часть моего ответа будет оттуда. Соответствующая документация Rails для этого здесь .

Быстрые определения:

  • Slug: часть URL для идентификации записи, в вашем случае organization_name
  • Первичный ключ: уникальный идентификатор для записей в базе данных. Обычно это так и должно быть id.

Резюме

Если вы введете organization_path(@organization), он автоматически будет использовать атрибут id в URL. Чтобы настроить использование organization_name, вам необходимо внести 2 изменения:

  1. Переопределить параметры маршрута в файле routes.rb.
  2. Переопределить метод to_param в модели

1. Переопределить параметры маршрута

На данный момент, если вы запустите rails routes, ваши маршруты будут выглядеть так:

organizations       GET    /organizations(.:format)                     organizations#index
                    POST   /organizations(.:format)                     organizations#create
new_organization    GET    /organizations/new(.:format)                 organizations#new
edit_organization   GET    /organizations/:id/edit(.:format)            organizations#edit
organization        GET    /organizations/:id(.:format)                 organizations#show
                    PATCH  /organizations/:id(.:format)                 organizations#update
                    PUT    /organizations/:id(.:format)                 organizations#update
                    DELETE /organizations/:id(.:format)                 organizations#destroy

Пути edit_organization и organization используют id в качестве параметра для поиска вашей организации.

Используйте это, чтобы переопределить параметры маршрута

Rails.application.routes.draw do
  resources :organizations, param: :organization_name
end

Теперь rails routes покажет, что ваши маршруты выглядят так:

organizations       GET    /organizations(.:format)                                    organizations#index
                    POST   /organizations(.:format)                                    organizations#create
new_organization    GET    /organizations/new(.:format)                                organizations#new
edit_organization   GET    /organizations/:organization_name/edit(.:format)            organizations#edit
organization        GET    /organizations/:organization_name(.:format)                 organizations#show
                    PATCH  /organizations/:organization_name(.:format)                 organizations#update
                    PUT    /organizations/:organization_name(.:format)                 organizations#update
                    DELETE /organizations/:organization_name(.:format)                 organizations#destroy

2. Переопределить параметры модели

По умолчанию organization.to_param вернет id организации. Это должно быть отменено, сделайте это, изменив вашу модель:

class Organization < ApplicationRecord
  def to_param
    organization_name
  end
end

Заключение и предупреждение

Теперь вы можете продолжать использовать перенаправления и формы как обычно, но вместо маршрута с использованием id теперь будет использоваться название организации.

Кроме того, удачи в вашем майнинг-пуле! Дай мне знать, какую монету ты добываешь, и я могу присоединиться!

Кроме того, я не освещал это, потому что это не является частью вашего первоначального вопроса, но вы должны убедиться, что organization_name уникален! Вы должны не только добавить в режим ограничение уникальности validates :organization_name, uniqueness: true, но и применить его на уровне базы данных при миграции.

Приложение 1: Настройка для маршрутов

Когда ваши маршруты определены так:

  resources :organizations, :only => [:show] do
    post  'update_work'
    get   'get_work'
    get   'mine'
    get   'poll'
    post  'submit'
    get   'home'
    get   'terms_of_use'
  end

Ваши маршруты будут такими:

 organization_update_work POST   /organizations/:organization_id/update_work(.:format)                                    organizations#update_work
    organization_get_work GET    /organizations/:organization_id/get_work(.:format)                                       organizations#get_work
        organization_mine GET    /organizations/:organization_id/mine(.:format)                                           organizations#mine
        organization_poll GET    /organizations/:organization_id/poll(.:format)                                           organizations#poll
      organization_submit POST   /organizations/:organization_id/submit(.:format)                                         organizations#submit
        organization_home GET    /organizations/:organization_id/home(.:format)                                           organizations#home
organization_terms_of_use GET    /organizations/:organization_id/terms_of_use(.:format)                                   organizations#terms_of_use
             organization GET    /organizations/:id(.:format)                                                             organizations#show

Изменение param примерно так:

  resources :organizations, :only => [:show], param: :organization_name do
    post  'update_work'
    get   'get_work'
    get   'mine'
    get   'poll'
    post  'submit'
    get   'home'
    get   'terms_of_use'
  end

Изменит ваши маршруты на

 organization_update_work POST   /organizations/:organization_organization_name/update_work(.:format)                     organizations#update_work
    organization_get_work GET    /organizations/:organization_organization_name/get_work(.:format)                        organizations#get_work
        organization_mine GET    /organizations/:organization_organization_name/mine(.:format)                            organizations#mine
        organization_poll GET    /organizations/:organization_organization_name/poll(.:format)                            organizations#poll
      organization_submit POST   /organizations/:organization_organization_name/submit(.:format)                          organizations#submit
        organization_home GET    /organizations/:organization_organization_name/home(.:format)                            organizations#home
organization_terms_of_use GET    /organizations/:organization_organization_name/terms_of_use(.:format)                    organizations#terms_of_use
             organization GET    /organizations/:organization_name(.:format)                                              organizations#show

Что должно прекрасно работать с вашим перенаправлением.

0 голосов
/ 05 мая 2018

Существует gem friendly_id, который делает именно то, что вы просите: https://github.com/norman/friendly_id

Вы добавляете,

gem 'friendly_id'

Затем bundle install и запустите rails generate friendly_id и rails db:migrate

в ваш Gemfile и,

class Organization < ApplicationRecord
  extend FriendlyId
  friendly_id :name, use: :slugged
end

к вашей модели

class OrganizationController < ApplicationController
  def show
    @user = Organization.friendly.find(params[:id])
  end
end

к вашему контроллеру.

Это предотвращает проблемы, с которыми вы можете столкнуться в ответе Kkulikovskis, где вы должны убедиться, что вы ищете вещи правильно.

0 голосов
/ 06 мая 2018

ОК, если вы не заинтересованы в использовании какого-либо драгоценного камня, вы можете без драгоценного камня, как

class Model < ApplicationRecord
   def to_param  # overridden
      organization_name
    end
end

в этом случае вам необходимо убедиться, что имя organization_name является уникальным, для уникальности organization_name вы можете использовать проверку таким образом

validates_uniqueness_of :organization_name

тогда модель будет выглядеть так

class Model < ApplicationRecord
    validates_uniqueness_of :organization_name

    def to_param  # overridden
      organization_name
    end
end

и теперь для контроллера, используя find_by_organization_name(params[:organization_name]) вместо find(params[:id]).

Второй вариант

Вы не можете ничего изменить в своем контроллере, если используете его только в этой модели

class Model < ApplicationRecord
    def to_param  # overridden
      organization_name
      "#{id} #{organization_name}".parameterize
    end
end

тогда URL выглядит так /10-microsoft.

См. Этот to_param метод. Полный справочник с драгоценным камнем или без драгоценного камня Rails Friendly URLs

RailsCasts.com создал эпизод для Pretty URLs с FriendlyId, вы можете проверить его для получения идеи.

Из комментария

Я не думаю, что происходит, но уверен, что что-то не так с отношениями, можешь проверить вот так

redirect_to(worker.organizations.first)
#=> OR
redirect_to organization_path(worker.organizations.first.id)

Обновление

Я думаю, worker.organization как-то не хватает, вы бы попробовали вот так?

if worker && worker.organizations.present?
   redirect_to(worker.organizations.first)
....

метод present, проверяющий worker.organizations не пустым.

Я не знаю об отношениях, вы можете попробовать вот так и сообщить мне, что происходит, если они не работают, тогда я настоятельно рекомендую опубликовать модели с концепцией отношений.

Обновление 2 после обновления вопроса

Во-первых, вам не нужны отношения through, потому что они используют отношения Many To Many. Ваши отношения One To One, тогда ваша модель будет выглядеть так

class StratumWorker < ApplicationRecord

    has_one :organization_worker
....

has_one: организация,: через =>: организация_работник

organization_worker.rb файл вроде этого

class OrganizationWorker < ApplicationRecord

    belongs_to :stratum_worker 

    #=> Add code what you need like for URL which was the actual motive in this post
....

Тогда действие выглядит так

def index
    worker_id = params[:worker_id]
    worker = StratumWorker.find_by_id(worker_id)
    if worker && worker.organization_worker.present?
      #redirect_to(worker.organization_worker)
      redirect_to organization_path(worker.organization_worker)
    else
      render :file => "#{Rails.root}/public/404", layout: false, status: 404
    end
end

и шоу-экшн

OrganizationWorker.find(params:id)

Я думаю, что проблема решится сейчас. Если вы по-прежнему получаете ошибки, прочитайте, пожалуйста, отношения One To One снова и снова, пока не очистите концепцию отношений.

Надеюсь, это поможет.

0 голосов
/ 03 мая 2018

Метод, который вызывается под капотом для генерации идентификатора: to_param

, поэтому в вашем случае, чтобы получить желаемый результат, вы должны добавить это к вашему Organization классу:

class Organization < ApplicationRecord
  ...

  def to_param
    name
  end

  ...
end

!!! WARNING !!! - поскольку Rails также использует параметр на другой стороне (например, в методе show Organization.find(params[:id]) использует идентификатор URL), теперь это будет params[:id] == "some_organization_name", поэтому измените свой поиск экземпляров соответственно - в действии show, например, используйте Organization.find_by!(name: params[:id]) и так далее

Что касается вашей ошибки маршрутизации - убедитесь, что worker.organization не nil.

...