mail_form gem rspec "undefined method `email' for" - ruby-on-rails

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

Can you make a form object work for new and edit actions if the form itself is never persisted?

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

Create multiple Addresses for one User with Formtastic

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

Creating has_and_belongs_to_many objects within the same form in rails

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

undefined method `model_name_question' for #..Rails 4

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.

Rails: Form inputs not saving after submit

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.

Resources