Как я могу использовать тег "форма", а не "форма" в этом файле
Я новичок в Ruby on Rails,и мне очень помогла превосходная книга Майкла Хартла: Ruby on Rails Tutorial. Я добрался до главы 8 и теперь перехожу к упражнениям в этой главе. У меня есть ( я предполагаю, что типичный "новичок") проблема с Упражнением 1. В этом упражнении задается вопрос " 1.Рефакторинг форма входа использовать form_tag в form_for."Я уже два дня пытаюсь найти помощь в этом в Stackoverflow, Google, Railscast и многих других "веб-поисках". и я, кажется, не нахожу помощи, которая мне нужна, чтобы решить эту проблему. Файл, который я пытаюсь изменить с помощью form_tag, находится ниже:
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_for(:session, url: sessions_path) do |f| %>
<%= f.label :email %>
<%= f.text_field :email %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.submit "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
Я использую Rails 3.2.3 в этом приложении. Может ли кто-нибудь указать мне правильное направление? Может ли кто-нибудь помочь мне с этой проблемой? Я был бы вам очень признателен.
Это реализация, которая использует form_tag:
<% provide(:title, "Sign in") %>
<h1>Sign in</h1>
<div class="row">
<div class="span6 offset3">
<%= form_tag( url: sessions_path ) do %>
<%= label_tag :email %>
<%= text_field_tag :email %>
<%= label_tag :password %>
<%= password_field_tag :password %>
<%= submit_tag "Sign in", class: "btn btn-large btn-primary" %>
<% end %>
<p>New user? <%= link_to "Sign up now!", signup_path %></p>
</div>
</div>
Я использую Rspec 2.9.0 и ниже приведены ошибки тесты:
describe "signin page" do
before { visit signin_path }
it { should have_selector('h1', text: 'Sign in') }
it { should have_selector('title', text: 'Sign in') }
end
И
describe "with invalid information" do
before { click_button "Sign in" }
it { should have_selector('title', text: 'Sign in') }
it { should have_selector('div.alert.alert-error', text: 'Invalid') }
describe "after visiting another page" do
before { click_link "Home" }
it { should_not have_selector('div.alert.alert-error') }
end
end
И
describe "with valid information" do
let(:user) { FactoryGirl.create(:user) }
before do
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Sign in"
end
it { should have_selector('title', text: user.name) }
it { should have_link('Profile', href: user_path(user)) }
it { should have_link('Sign out', href: signout_path) }
it { should_not have_link('Sign in', href: signin_path) }
describe "followed by signout" do
before { click_link "Sign out" }
it { should have_link('Sign in') }
end
end
Вот мой файл маршрутов:
SampleApp::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
get "users/new"
root to: 'static_pages#home'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
match '/help', to: 'static_pages#help'
match '/about', to: 'static_pages#about'
match '/contact', to: 'static_pages#contact'
end
5 ответов:
Я только что завершил это упражнение, так что я ни в коем случае не эксперт; однако это код, который работал на меня и прошел все тесты:
../приложение/просмотров/сессий/новый.формат html.erb
<% provide(:title, "Sign in") %> <h1>Sign in</h1> <div class="row"> <div class="span 6 offset 3"> <%= form_tag sessions_path do %> <%= label_tag :email %> <%= text_field_tag :email, params[:email] %> <%= label_tag :password %> <%= password_field_tag :password %> <%= submit_tag "Sign in", class: "btn btn-large btn-primary" %> <% end %> <p>New User?<%= link_to "Sign Up Now", signup_path %> </p> </div> </div>Мне также нужно было изменить ../app / controllers/sessions_contoller
Хотя это работает, я не совсем уверен, почему это происходит; если бы кто-то мог объяснить, почему требуются изменения в контроллере, это было бы очень ценно. Я знаю, что это может быть поставлено под вопрос. отдельный вопрос, но он тесно связан с OP, и я уверен, что мы оба найдем его чрезвычайно полезным для понимания не только того, как заставить это работать, но и почему это работает таким образом. Ниже приведены исходные файлы представления и контроллера:class SessionsController < ApplicationController def new end def create user = User.find_by_email(params[:email]) if user && user.authenticate(params[:password]) session[:user] = user.id sign_in user redirect_to user else flash.now[:error] = 'Invalid email/password combination' render 'new' end end def destroy sign_out redirect_to root_path end endОригинал 'form_for' новый.формат html.erb:
<% provide(:title, "Sign in") %> <h1>Sign in</h1> <div class="row"> <div class="span6 offset3"> <%= form_for(:session, url: sessions_path) do |f| %> <%= f.label :email %> <%= f.text_field :email %> <%= f.label :password %> <%= f.password_field :password %> <%= f.submit "Sign in", class: "btn btn-large btn-primary" %> <% end %> <p>New user? <%= link_to "Sign up now!", signup_path %></p> </div> </div>И исходный sessions_controller:
class SessionsController < ApplicationController def new end def create user = User.find_by_email(params[:session][:email]) if user && user.authenticate(params[:session][:password]) sign_in user redirect_to user else flash.now[:error] = 'Invalid email/password combination' render 'new' end end def destroy sign_out redirect_to root_path end end
Я работаю над тем же этапом урока, и ваш вопрос помог мне найти свой путь.
Использование label и text_field вместо label_tag и text_field_tag работает нормально, и вам не нужно менять код контроллера (это дает тот же HTML-код, что и с оригинальным методом form_for).
<%= form_tag(sessions_path) do %> <%= label :session, :email %> <%= text_field :session, :email %> <%= label :session, :password %> <%= password_field :session, :password %> <%= submit_tag("Sign in", class: "btn btn-large btn-primary") %> <% end %>Вы можете прочитать подробности в http://guides.rubyonrails.org/form_helpers.html#dealing-with-model-objects
Меня поймали на том, что я не назвал поля правильно. Когда вы просматриваете исходный код оригинала, он показывает вам схему именования.
<%= form_tag(sessions_path) do %> <%= label_tag 'session_email', 'Email' %> <%= text_field_tag 'session[email]' %> <%= label_tag 'session_password', 'Password' %> <%= password_field_tag 'session[password]' %> <%= submit_tag "Sign in", class: "btn btn-large btn-primary" %> <% end -%>
У вас есть Session_Helper, который вы не используете в своей реализации.
Отредактируйте вспомогательные методы.
def sign_in(user) cookies.permanent[:remember_token] = user.remember_token session[:user_id] = user.id end def sign_out cookies.delete(:remember_token) session[:user_id] = nil endТогда вы можете просто использовать соответствующие методы в вашем контроллере сеанса. Это более аккуратная реализация, которая следует модульному подходу к проектированию. Там также, кажется, есть проблемы с rspec.
describe "with valid information" do let(:user) { FactoryGirl.create(:user) } before do fill_in "Email", with: user.email.upcase fill_in "Password", with: user.password click_button "Sign in" end it { should have_selector('title', text: user.name) } it { should have_link('Profile', href: user_path(user)) } it { should have_link('Sign out', href: signout_path) } it { should_not have_link('Sign in', href: signin_path) }Несмотря на то, что все правильно, когда вы посещаете страницу, эти тесты помечены. Я думаю, что вам нужно изменить
В любом случае, мне любопытно, в чем проблема с rspec, если у кого-то есть идея! Я думаю, что эта проблема связана сbefore do, потому что если бы это было делая то, что вы хотите, чтобы он сделал, тесты пройдут.user.email.upcase. Вам не нужно.upcase, Когда вы удалите его тесты пройдут.