Rails bố trí mỗi hành động?


165

Tôi sử dụng một bố cục khác cho một số hành động (chủ yếu là cho hành động mới trong hầu hết các bộ điều khiển).

Tôi tự hỏi cách tốt nhất để xác định bố cục sẽ là gì? (Tôi đang sử dụng 3 hoặc nhiều bố cục khác nhau trong cùng một bộ điều khiển)

Tôi không thích sử dụng

kết xuất: layout => 'name'

Tôi thích làm

bố cục 'tên' ,: only => [: new]

Nhưng tôi không thể sử dụng nó để chỉ định 2 hoặc nhiều bố cục khác nhau.

Ví dụ:

Khi tôi gọi bố cục 2 lần trong cùng một bộ điều khiển, với các tên bố cục khác nhau và các tùy chọn chỉ khác nhau, lần đầu tiên sẽ bị bỏ qua - những hành động đó không hiển thị trong bố cục tôi đã chỉ định.

Lưu ý: Tôi đang sử dụng Rails 2.


1
Tài liệu hướng dẫn của Rails: guide.rubyonrails.org/,
Kevin

1
Điểm tốt. Tài liệu cho Rails 2: guide.rubyonrails.org/v2.3.11/ trên
Kevin

2
(Ngoài ra, tôi đã đăng hướng dẫn để giúp những độc giả tương lai. Tôi không nghi ngờ gì về vấn đề của bạn đã được giải quyết từ lâu ;-)
Kevin

Câu trả lời:


297

Bạn có thể sử dụng một phương pháp để thiết lập bố cục.

class MyController < ApplicationController
  layout :resolve_layout

  # ...

  private

  def resolve_layout
    case action_name
    when "new", "create"
      "some_layout"
    when "index"
      "other_layout"
    else
      "application"
    end
  end
end

22
Tuyệt thật, cảm ơn nhé. Và trong trường hợp ai đó muốn làm những điều đơn giản hơn với một lớp lót, điều sau đây là có thể. Nó dễ dàng để đọc và đặt ở trên cùng của bộ điều khiển. ---layout Proc.new{ ['index', 'new', 'create'].include?(action_name) ? 'some_layout' : 'other_layout' }
holli

1
Điều này có ảnh hưởng lớn đến hiệu suất ứng dụng nếu nhiều bố cục khác nhau đang sử dụng nói một số tệp css & js khác nhau không?
Noz

15
-1: Quá phức tạp. Nhận xét dưới đây ( stackoverflow.com/a/21203783/285154 ) là lựa chọn tốt nhất.
dimitarvp

Cảm ơn! Đây vẫn là một vấn đề trong Rails 4.2, có lẽ chỉ khi bạn đang sử dụng bộ điều khiển kế thừa ở nhiều cấp độ. Tôi đã sử dụng phương pháp trước đây, nhưng không nghĩ đến việc kiểm tra rằng khi tôi gặp vấn đề bây giờ, cảm ơn một lần nữa.
244an

@dimitko không phải vậy, tôi đã tham khảo giải pháp đó trong chính câu hỏi. Nó không hoạt động nếu bạn muốn sử dụng 3 hoặc nhiều bố cục khác nhau (như chính xác là trường hợp của tôi).
mrbrdo

201

Nếu bạn chỉ chọn giữa hai bố cục, bạn có thể sử dụng :only:

class ProductsController < ApplicationController
   layout "admin", only: [:new, :edit]
end

hoặc là

class ProductsController < ApplicationController
   layout "application", only: [:index]
end

2
Chà, vấn đề với điều này là bạn không thể truy cập các đối tượng như current_user để xác định bố cục một cách có điều kiện
Andrew K

@AndrewK Tự động chọn bố cục dường như không phải là một phần của câu hỏi.
Nick

11
Nếu bất kỳ ai trong số các bạn đọc câu hỏi bạn sẽ biết đây không phải là câu trả lời đúng, vì tôi đã mô tả giải pháp này trong chính câu hỏi và tại sao nó không hoạt động trong trường hợp của tôi (3 bố cục trở lên).
mrbrdo

2
Giống như mrbrdo đã nói, đây không phải là câu trả lời. Câu hỏi của ông đặc biệt chỉ ra (I am using 3 or more different layouts in the same controller). Câu trả lời này cho phép bố trí và không bố trí, không bố trí khác nhau.
Michael

49

Bạn có thể chỉ định bố cục cho một hành động riêng lẻ bằng cách sử dụng answer_to :

  def foo
    @model = Bar.first
    respond_to do |format|
      format.html {render :layout => 'application'}
    end
  end

Đối với tôi đây là câu trả lời linh hoạt hơn. DRYing mọi thứ bằng cách áp dụng layout "[...]" to the controller class only allows one statement effectively. If you have more than two layouts to deal with (say, admin, generic_app, tailored_app), you will experience Render và / hoặc redirect được gọi nhiều lần trong lỗi này `; và bạn không có lựa chọn nào khác ngoài sử dụng gợi ý này.
Jerome

1
Câu trả lời này là tốt nhất, đơn giản và gọn gàng trái ngược với việc sử dụng các phương thức với chuyển đổi hoặc nếu các câu lệnh bên trong.
kev 7/07/2015

ngoài ra nó có thể chỉ định tệp erb và bố trí cả hai: format.html { render 'custom_index', layout: 'application' } theo cùng một cách.
thatway_3

12

Bạn cũng có thể chỉ định bố cục cho hành động bằng cách sử dụng kết xuất:

def foo
  render layout: "application"
end


7

Nhiều cách khác nhau để xác định bố cục trong bộ điều khiển:

  1. Trong đoạn mã sau, bố cục application_1 được gọi theo chỉ mục và hiển thị hành động của Trình điều khiển người dùng và bố cục ứng dụng (bố cục mặc định) được gọi cho các hành động khác.

    class UsersController < ApplicationController
      layout "application_1", only: [:index, :show]
    end
  2. Trong đoạn mã sau, bố cục application_1 được gọi cho tất cả hành động của bộ điều khiển Người dùng.

    class UsersController < ApplicationController
       layout "application_1"
    end
  3. Trong đoạn mã sau, bố trí application_1 chỉ được gọi cho hành động kiểm tra của bộ điều khiển Người dùng và đối với tất cả bố cục ứng dụng hành động khác (mặc định) được gọi.

        class UsersController < ApplicationController
          def test
            render layout: "application_1"
          end
        end

5

Độ chính xác :

Một cách không thực sự nhưng hoạt động DRY là những gì bạn thấy ở trên, nhưng với độ chính xác: bố cục cần phải nằm sau các biến của bạn để làm việc ("@some"). Như :

def your_action
   @some = foo
   render layout: "your_layout"
end

Và không :

def your_action
   render layout: "your_layout"
   @some = foo
   @foo = some
end

Nếu bạn thực hiện thao tác trước ... nó cũng sẽ không hoạt động.

Hy vọng nó giúp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.