how can I write a test mail_form gem?
Вut the test gives an error.
How to associate a OrderForm and MailForm?
I have :
model:
class OrderForm < MailForm::Base
attributes :name
attributes :email
attributes :phone_number
attributes :order_name
attributes :address
attributes :file_1, attachment: true
def mail_attachments
[:file_1]
end
controller, where:
class OrdersController < ApplicationController
def create
#order_form = OrderForm.new(params[:order_form])
#order_form.deliver
redirect_to root_path, notice: 'Заявка отправлена'
end
end
end view(form of sending a letter):
orders/new.html.haml_spec.rb
=form_for #order_form, url: orders_path, method: :post do |f|
=f.text_field :name, placeholder: 'ФИО', class: 'gui-input'
=f.text_field :email, placeholder: 'Email', class: 'gui-input'
=f.text_field :phone_number, placeholder: 'Номер телефона',
end I write test:
require 'rails_helper'
RSpec.describe "orders/new", type: :view do
it do
assign(:order, build(:order))
render
expect(rendered).to have_field :name
end
end
check the output of rake routes, url orders/new will execute the orders#new action and render the view orders/new.html.erb
GET /orders/new orders#new return an HTML form for creating a new order
new.html.erb will use the variables from your orders#new action. You are missing those variables
class OrdersController < ApplicationController
def new
#order_form = OrderForm.new
end
def create
#order_form = OrderForm.new(params[:order_form])
#order_form.deliver
redirect_to root_path, notice: 'Заявка отправлена'
end
end
Related
I'm trying to make a form object work for new User and edit User actions. The form object creates or updates a User through it's save method, but the form object itself is never persisted so Rails always tries to make a POST even though I'm specifying different routes in the simple_form_for url.
Is there any way to make it work for both actions?
UsersController.rb:
class Admin::UsersController < AdminController
def new
#user_form = UserForm.new(account_id: current_account.id)
end
def create
#user_form = UserForm.new(user_form_params)
if #user = #user_form.save
flash[:success] = "User created"
redirect_to admin_user_path(#user)
else
render "new"
end
end
def edit
#user_form = UserForm.new(existing_user: #user, account_id: current_account.id)
end
def update
if #user.update(user_form_params)
flash[:success] = "User saved"
redirect_to admin_user_path(#user)
else
render "edit"
end
end
end
UserForm.rb
class UserForm
include ActiveModel::Model
include ActiveModel::Validations::Callbacks
attr_accessor :fname, :lname, :email
def initialize(params = {})
super(params)
#account = Account.find(account_id)
#user = existing_user || user
end
def user
#user ||= User.new do |user|
user.fname = fname
user.lname = lname
user.email = email
end
end
def save
#user.save
#user
end
end
_form.html.erb
<%= simple_form_for #user_form, url: (#user.present? ? admin_user_path(#user) : admin_users_path) do |f| %>
<%= f.input :fname %>
<%= f.input :lname %>
<%= f.input :email %>
<%= f.submit %>
end
The new/create flow works fine, but editing an existing User returns
No route matches [POST] "/admin/users/69"
class UserForm
# ...
def to_model
#user
end
end
<%= simple_form_for #user_form, url: [:admin, #user_form] do |f| %>
<%= f.input :fname %>
<%= f.input :lname %>
<%= f.input :email %>
<%= f.submit %>
end
When you pass a record to form_for (which SimpleForm wraps), form_with or link_to the polymorphic routing helpers call to_model.model_name.route_key or singular_route_key depending on if the model is persisted?. Passing [:admin, #user_form] will cause the polymorphic route helpers to use admin_users_path instead of just users_path.
On normal models to_model just returns self.
https://api.rubyonrails.org/v6.1.4/classes/ActionDispatch/Routing/PolymorphicRoutes.html
I currently have the following setup in my Rails 5 Application:
class User < ApplicationRecord
has_many :addresses
accepts_nested_attributes_for :addresses
end
class Address < ApplicationRecord
belongs_to :user
end
The corresponding controller looks like this:
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
if #user.save
redirect_to users_path
else
render 'new', notice: "User could not be created"
end
end
private
def user_params
params.require(:user).permit(
:first_name, :last_name, :email, ...
)
end
end
Each User is supposed to have multiple Addresses (e.g. for billing and shipping) that I need to set during user creation. The form (made with formtastic) looks like this (outtake):
= semantic_form_for #user do |user|
= user.input :first_name
= user.semantic_fields_for Address.new do |shipping_address|
= shipping_address.input :city
= shipping_address.input :usage,
as: :hidden,
input_html: { value: 'shipping' }
= user.semantic_fields_for Address.new do |billing_address|
= billing_address.input :city
= billing_address.input :usage,
as: :hidden,
input_html: { value: 'billing' }
The problem is ofc that only the latter address is present in the sites parameters, so only one will be created.
How can I create multiple address for the same user?
To create nested records you should and seed the record and pass the association to fields_for.
For example you would do:
class UsersController < ApplicationController
# ...
def new
#user = User.new
# if we skipped this step there would be no address inputs on the form.
#user.addresses.new(value: 'shipping')
#user.addresses.new(value: 'billing')
end
end
<%= semantic_form_for(#user) do |f| %>
# ...
# fields_for iterates through #user.addresses creating
# inputs for each
<% f.semantic_fields_for :addresses do |a| %>
<%= a.inputs :street %>
<%= a.input :value, as: :hidden %>
<% end %>
<% end %>
Which would give the following params hash:
{
user: {
addresses_attributes: [
{
street: 'Wall Street',
value: 'shipping'
},
{
street: 'Broadway',
value: 'billing'
},
]
}
}
Note that proper pluralization is extremely important here!
You can then pass this to your user model and accepts_nested_attributes will do the rest of the work.
class UsersController < ApplicationController
# ...
def create
#user = User.new(user_params)
if #user.save
#...
else
# ...
end
end
private
def user_params
params.require(:user)
.permit(:email, :password, addresses_attributes: [:value, :street, :city]) # etc
end
end
I'm building a rails app, using devise for authentication and cancan for authorization. I have a form where you can create a "post" and each post has_and_belongs_to many "tags".
I want to create a system for creating tags similar to stack overflow, where the tags are simply inputed via a single text box and then converted to the appropriate tag objects on the server side. Initially I simply had a text box where I could type in a string and the string would be parsed as such in the controller
#post.tags << params[:post][:tags].split(' ').map{ |name| Tag.createOrReturnExisting name}
and that worked perfectly.. until I added cancan authorization, which required me to add
def post_params
params.require(:post).permit(:title,:description,:tags,:content,:types_id)
end
to my controller , which now causes the following error to be thrown upon trying to create a Post undefined method each for "Tag1 Tag2 Tag3\r\n":String I'm assuming this is because its trying to treat the string from the textbox like an array of tags before I've had a chance to format it.
So my question is, how must I format my controller, model, or view to be able to parse the string before it gets to the post_params method?
here's my models, view, and controller
Tag Model
class Tag < ActiveRecord::Base
has_and_belongs_to_many :post, join_table: 'tag_posts'
def self.createOrReturnExisting title
if Tag.any? {|tag| tag.title == title}
logger.debug "Tag: #{title} already exists"
Tag.find_by title: title
else
logger.debug "Tag: #{title} created"
Tag.new title: title
end
end
end
Post Model
class Post < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :tags, join_table: 'tags_posts'
has_one :type
validates :title, presence: true, length: { maximum: 50 }
validates :description, presence: true, length: { maximum: 255 }
validates :types_id, presence: true, length: { maximum: 255 }
end
new.html.erb
<h1>Post#new</h1>
<p>Find me in app/views/post/new.html.erb</p>
<%= form_for #post do |f| %>
Title: <%= f.text_field :title %>
Description: <%= f.text_area :description %>
Type: <%= f.collection_select( :types_id, Type.all, :id, :title ) %>
Content: <%= f.text_area :content%>
Tags: <%= f.text_area :tags%>
<%= f.submit %>
<% end %>
PostController
class PostsController < ApplicationController
load_and_authorize_resource
def miniList
render 'miniList'
end
def create
#post = Post.new
#post.title = params[:post][:title]
#post.description = params[:post][:description]
#post.content = params[:post][:content]
#tagStrings = params[:post][:tags].split(' ')
puts #tagStrings
#tagStrings.map do |name|
#tags << Tag.createOrReturnExisting name
end
#post.tags = #tags
#post.types_id = params[:post][:types_id]
if #post.save!
flash[:success] = "Post Saved Successfully"
else
flash[:error] = "Post not saved"
end
current_user.posts << #post
redirect_to :root
end
def new
#post = Post.new
render 'new'
end
def edit
end
def update
end
def delete
end
private
def post_params
params.require(:post).permit(:title,:description,:tags,:content,:types_id)
end
end
I figured it out, what I needed to do was change load_and_authorize_resource to authorize_resource since I don't want cancan messing with my parameters, this will just have it check authorization for my controller actions, and then leave the rest alone. I still wish there was a more intuitive way to do it, but this accomplishes what I need
I am getting this error after submitting the form:(in the index page)
<%= simple_form_for(#quiz, html: {class: 'form-vertical' }) do |f| %>
<%= render 'shared/error_messages_question' %>
<%= f.input_field :content, :rows => 3, :style => "width:80%", :placeholder => "enter your question." %>
<%= f.button :submit %>
<% end %>
I have question model:
class Question < ActiveRecord::Base
validates :question, presence: true
belongs_to :category
belongs_to :questioner
end
and questions controller:
class QuestionsController < ApplicationController
def index
#quiz = Question.new
#questioner = Questioner.new
end
def new
#quiz = Question.new(quiz_params)
end
def show
#quiz = Question.find(params[:id])
end
def edit
#quiz = find(params[:id])
raise "Question Not edited!" unless #quiz
end
def create
#quiz = Question.new(quiz_params)
if #quiz.save
flash[:success] = 'You have successfully posted the questions!'
redirect_to questions_path
else
flash[:error] = "Please review the problems below."
# render 'new'
redirect_to questions_path
end
end
private
def quiz_params
params.require(:question).permit(:content, :answered, :questioner_id, :category_id)
end
end
what could b the problem?
in the rails server I have this:
Completed 500 Internal Server Error in 5ms
NoMethodError - undefined method `question' for #<Question:0x0000000433dfc0>:
activemodel (4.0.2) lib/active_model/attribute_methods.rb:439:in `method_missing'
The issue may potentially be related to this validation line
validates :question, presence: true
It assumes your Question model has a :question attribute. In other words, makes sure there is a proper question database column in the questions database table.
If this is not the case, fix the either the table or the validation accordingly.
why wont anything entered into this form save?
new.html.erb
<%= form_for [#requestable, #request] do |f| %>
<%= f.label :status %>
<%= f.text_field :status, rows: 8 %>
<%= f.submit "Request", :class => 'btn'%>
<% end %>
requests_controller.rb
class RequestsController < ApplicationController
before_filter :load_requestable
def index
#requests = #requestable.requests
end
def new
#request = #requestable.requests.new
end
def create
#request = #requestable.requests.new(params[:status])
if #request.save
redirect_to [#requestable, :requests], notice: "Request sent."
else
render :new
end
end
private
def load_requestable
klass = [Company, Profile].detect { |c| params["#{c.name.underscore}_id"]}
#requestable = klass.find(params["#{klass.name.underscore}_id"])
end
end
my controller is based on this
https://github.com/railscasts/154-polymorphic-association-revised/blob/master/blog-after/app/controllers/comments_controller.rb
request.rb
class Request < ActiveRecord::Base
attr_accessible :status
belongs_to :requestable , polymorphic: true
belongs_to :profile
validates :status, presence: true
end
This is being produced by my debuger
--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess
utf8: ✓
authenticity_token: /0H2k89HN4JVXBPsoFWen5rUfx2xr4p5hr1uDSQVlcA=
request: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
status: pending
commit: Request
action: create
controller: requests
company_id: '1'
Take a look at what's in your params hash. The status field is probably in something like params[:request][:status]. Assuming standard activerecord-y stuff, you want to pass the hash for the whole request object to .new.